﻿#******************************************************************************************************************************
# SPPackager.SPDeploy.Deploy.ps1 - Perform the instalation, upgrade and retraction of Ms Sharepoint Applications fast, easy and efficient
# Script version 5.5 - June, 21th of 2013
# Frederico Souza Lima (fredericosl@hotmail.com)
# Michael Capela (michaelcapela@hotmail.com)
# Copyright (c) 2012-2013 
#******************************************************************************************************************************

#******************************************************************************************************************************
# Powershell Global Parameters Definition
#******************************************************************************************************************************
If ($Host.Name -eq "PowerGUIScriptEditorHost") { cls; }
$ErrorActionPreference = "Stop";
$RawUI = (Get-Host).UI.RawUI;
$RawUI.BackgroundColor = "Black";
$RawUI.ForegroundColor = "White";

#******************************************************************************************************************************
# Load Microsoft Sharepoint Snapin
#******************************************************************************************************************************

if ((Get-PSSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue) -eq $null) {
    Add-PSSnapin "Microsoft.SharePoint.PowerShell"
}

#******************************************************************************************************************************
# Load .Net Assemblies used by functions
#******************************************************************************************************************************

[void][System.Reflection.Assembly]::LoadWithPartialName("System")
[void][System.Reflection.Assembly]::LoadWithPartialName("System.IO")
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Collections")
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Collections.Generic");
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Text");
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Text.RegularExpressions");
[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint");
[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Administration");
[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Publishing");
[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Utilities");
[void][System.Reflection.Assembly]::LoadWithPartialName("System.DirectoryServices.AccountManagement");

#******************************************************************************************************************************
# Define Global Constants
#******************************************************************************************************************************
if ((Get-Variable | Where-Object {$_.Name -eq "timerServiceName"}) -eq $null){
	Set-Variable timerServiceName -option Constant -value "SharePoint 2010 Timer";
}
if ((Get-Variable | Where-Object {$_.Name -eq "timerServiceInstanceName"}) -eq $null){
	Set-Variable timerServiceInstanceName -option Constant -value "Microsoft SharePoint Foundation Timer"
}
if ((Get-Variable | Where-Object {$_.Name -eq "sandboxServiceName"}) -eq $null){
	Set-Variable sandboxServiceName -option Constant -value "SharePoint 2010 User Code Host";
}
if ((Get-Variable | Where-Object {$_.Name -eq "sandboxServiceInstanceName"}) -eq $null){
	Set-Variable sandboxServiceInstanceName -option Constant -value "Microsoft SharePoint Foundation Sandboxed Code Service"
}

#******************************************************************************************************************************
# Define Globais Functions
#******************************************************************************************************************************

$script:LastNoNewline = $false;
function WriteMessage([bool]$NoNewline, [bool]$PrintDateTime, [string]$Message)
{ 
	if (!$NoNewline) {
		if ($script:LastNoNewline) {
			Write-Host "";
		}
		$script:LastNoNewline = $false;
	}
	else {
		$script:LastNoNewline = $true;
	}
	
	if ($PrintDateTime) {
		$Date = Get-Date;
		[string] $TextDate = "$Date - ";
	}
	
	Write-Host -NoNewline:$NoNewline $TextDate$Message;

}

#******************************************************************************************************************************
## OSTimer Functions
#******************************************************************************************************************************

function WaitForJobToFinish([string]$SolutionFileName)
{ 
    $JobName = "*solution-deployment*$SolutionFileName*"
    $job = Get-SPTimerJob | ?{ $_.Name -like $JobName }
    if ($job -eq $null) 
    {
        WriteMessage $false $true 'Timer job not found'
    }
    else
    {
        $JobFullName = $job.Name
        WriteMessage $true $true "Waiting to finish job $JobFullName"
        
        while ((Get-SPTimerJob $JobFullName) -ne $null) 
        {
            WriteMessage $true $false "."
            Start-Sleep -Seconds 2
        }
		
    }
}

function WaitForServiceJobToFinish()
{ 
    $JobName = "*job-service-instance*"
    $job = Get-SPTimerJob | ?{ $_.Name -like $JobName }
    if ($job -eq $null) 
    {
        WriteMessage $false $true 'Timer job not found';
    }
    else
    {
        $JobFullName = $job.Name
        WriteMessage $true $true "Waiting to finish job $JobFullName"
        
        while ((Get-SPTimerJob $JobFullName) -ne $null) 
        {
            WriteMessage $true $false ".";
            Start-Sleep -Seconds 2;
        }

    }
}

function StopSharePointServicesInFarm([Microsoft.SharePoint.Administration.SPFarm]$farm, [string]$ServiceInstanceName, [string]$ServiceName)
{
	foreach($server in $farm.Servers)
	{
		foreach($instance in $server.ServiceInstances)
		{
			if($instance.TypeName -eq $ServiceInstanceName)
			{
				[string]$serverName = $server.Name

				WriteMessage $false $true "Stopping '$ServiceName' service on $serverName server."

				$service = Get-WmiObject -ComputerName $serverName Win32_Service -Filter "DisplayName='$ServiceName'"
				$serviceInternalName = $service.Name
				sc.exe \\$serverName stop $serviceInternalName > $null

				WaitForServiceState $serverName $ServiceName "Stopped"
				
				break;
			}
		}
	}

}

function WaitForServiceState([string]$serverName, [string]$serviceName, [string]$serviceState)
{
	WriteMessage $true $true "Waiting for '$serviceName' service change their status to $serviceState on $serverName server."

	do
	{
		Start-Sleep 1
		WriteMessage $true $false "."
		$service = Get-WmiObject -ComputerName $serverName Win32_Service -Filter "DisplayName='$serviceName'"
	}
	while ($service.State -ne $serviceState)

}

function StartSharePointServicesInFarm([Microsoft.SharePoint.Administration.SPFarm]$farm, [string]$ServiceInstanceName, [string]$ServiceName)
{

	foreach($server in $farm.Servers)
	{
		foreach($instance in $server.ServiceInstances)
		{
			if($instance.TypeName -eq $ServiceInstanceName)
			{
				[string]$serverName = $server.Name

				WriteMessage $false $true "Starting '$ServiceName' service on $serverName server."

				$service = Get-WmiObject -ComputerName $serverName Win32_Service -Filter "DisplayName='$ServiceName'"
				[string]$serviceInternalName = $service.Name
				sc.exe \\$serverName start $serviceInternalName > $null

				WaitForServiceState $serverName $ServiceName "Running"
				
				break;
			}
		}
	}

}

function DeleteXmlFilesFromConfigCache([Microsoft.SharePoint.Administration.SPFarm]$farm)
{
	WriteMessage $false $true "Deleting XML files from configuration cache."

	[string] $path = ""

	foreach($server in $farm.Servers)
	{
		foreach($instance in $server.ServiceInstances)
		{
			if($instance.TypeName -eq $timerServiceInstanceName)
			{
				[string]$serverName = $server.Name
				
				WriteMessage $false $true "Deleting XML files from configuration cache on $serverName server."

				$path = "\\" + $serverName + "\c$\ProgramData\Microsoft\SharePoint\Config\*-*\*.xml"
				Remove-Item -path $path -Force
				
				break
			}
		}
	}
}

function ClearTimerCache([Microsoft.SharePoint.Administration.SPFarm]$farm)
{
	WriteMessage $false $true "Performing cache cleaning."

	[string] $path = ""

	foreach($server in $farm.Servers)
	{
		foreach($instance in $server.ServiceInstances)
		{
			if($instance.TypeName -eq $timerServiceInstanceName)
			{
				[string]$serverName = $server.Name

				WriteMessage $false $true "Cleaning Sharepoint Timer cache on $serverName server."
				
				$path = "\\" + $serverName + "\c$\ProgramData\Microsoft\SharePoint\Config\*-*\cache.ini"
				Set-Content -path $path -Value "1"
				
				break
			}
		}
	}

}

Function CleanupAndRestartTimer
{

	[Microsoft.SharePoint.Administration.SPFarm]$farm = [Microsoft.SharePoint.Administration.SPFarm]::get_Local()

	StopSharePointServicesInFarm $farm $timerServiceInstanceName $timerServiceName
	DeleteXmlFilesFromConfigCache $farm
	ClearTimerCache $farm
	StartSharePointServicesInFarm $farm $timerServiceInstanceName $timerServiceName

}

#******************************************************************************************************************************
## Other Functions
#******************************************************************************************************************************

function WebApplicationExists([string]$URL)
{
	WriteMessage $false $true "WebApplicationExists To be developed." 
	return $true;
}

function CreateWebApplication([string]$URL)
{
	WriteMessage $false $true "CreateWebApplication To be developed." 
}

function DropWebApplication([string]$URL)
{
	WriteMessage $false $true "DropWebApplication To be developed." 
}

function DisableCoauthoring([string]$URL)
{
	$mysite=Get-SPSite -Limit All | Where-Object {$_.Url -eq $URL};
	
	$mysite.WebApplication.WebService.DisableCoauthoring = $true;
	$mysite.WebApplication.WebService.Update();
	$mysite.WebApplication.DisableCoauthoring = $true;
	$mysite.WebApplication.Update();
}

function ConfigBrowserFileHandling([string]$URL, [string]$BrowserFileHandling)
{
	$SPWebApplication = Get-SPWebApplication $URL;
	$SPWebApplication.BrowserFileHandling = $BrowserFileHandling;
	$SPWebApplication.Update();
}

function GetBrowserFileHandling([string]$URL)
{
	$SPWebApplication = Get-SPWebApplication $URL;
	return $SPWebApplication.BrowserFileHandling.ToString();
}

function ConfigMaxQueryLookupFields([string]$URL, [int]$Value)
{
	$SPWebApplication = Get-SPWebApplication $URL;
	$SPWebApplication.MaxQueryLookupFields = $Value;
	$SPWebApplication.Update();
}

function GetMaxQueryLookupFields([string]$URL)
{
	$SPWebApplication = Get-SPWebApplication $URL;
	return $SPWebApplication.MaxQueryLookupFields;
}

function WebApplicationHasCoauthoring([string]$URL)
{
	$mysite=Get-SPSite -Limit All | Where-Object {$_.Url -eq $URL};
	
	if (($mysite.WebApplication.WebService.DisableCoauthoring -eq $true) -and ($mysite.WebApplication.DisableCoauthoring -eq $true)) {
		return $false;
	} else{return $true;}
	
}


function SiteCollectionExists([string]$SiteCollectionUrl)
{
	$Temp =Get-SPSite -Limit All | Where-Object {$_.Url -eq $SiteCollectionUrl}

	if ($Temp -ne $null) {return $true;} else{return $false;}
}

function CreateSiteCollection([string]$SiteCollectionURL, [string]$SiteCollectionName, [Int32]$SiteCollectionLanguage, [string]$SiteCollectionTemplate, [string]$SiteCollectionDescription)
{
	$SPWebTemplate = Get-SPWebTemplate |  Where-Object {$_.Title -eq $SiteCollectionTemplate};
	$SiteCollectionOwner = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name;

	$SPSite = New-SPSite $SiteCollectionURL -OwnerAlias $SiteCollectionOwner -Name $SiteCollectionName -Template $SPWebTemplate –Language $SiteCollectionLanguage -Description $SiteCollectionDescription;
}

function DropSiteCollection([string]$SiteCollectionUrl)
{
	Remove-SPSite –Identity $SiteCollectionUrl –Confirm:$False;
}

function ConfigureDefaultGroups([string]$WebUrl)
{
	$SPWeb = Get-SPWeb $WebUrl;
#Current Thread must be checked for Globalization: Task
#	$AssociatedVisitorGroupAppName = "Visitantes do " + $SPWeb.Title
#	$AssociatedOwnerGroupAppName = "Proprietários do " + $SPWeb.Title
#	$AssociatedMemberGroupAppName  = "Membros do " + $SPWeb.Title
	$AssociatedVisitorGroupAppName = $SPWeb.Title + " Visitors"
	$AssociatedOwnerGroupAppName = $SPWeb.Title + " Owners"
	$AssociatedMemberGroupAppName  = $SPWeb.Title + " Members"


	if (((IsGroupExists $WebUrl $AssociatedVisitorGroupAppName) -eq $false) -and ((IsGroupExists $WebUrl $AssociatedOwnerGroupAppName) -eq $false) -and ((IsGroupExists $WebUrl $AssociatedMemberGroupAppName) -eq $false)) {
	
		$SPWeb = Get-SPWeb $WebUrl;
		
		$SPWeb.AssociatedVisitorGroup = $null;
		$SPWeb.AssociatedMemberGroup = $null;
		$SPWeb.AssociatedOwnerGroup = $null;
			
		if ($SPWeb.IsRootWeb -eq $false -and $SPWeb.HasUniqueRoleDefinitions -eq $false){
			$SPWeb.BreakRoleInheritance($false);
		}
		
		$SPWeb.Update();
		
		$spWeb.CreateDefaultAssociatedGroups($spWeb.Site.Owner, $spWeb.site.Owner, $spWeb.Title)
		
		$spWeb.Properties["vti_associatevisitorgroup"] = $spWeb.AssociatedVisitorGroup.ID.ToString();
		$spWeb.Properties["vti_associateownergroup"] = $spWeb.AssociatedOwnerGroup.ID.ToString();
		$spWeb.Properties["vti_associatemembergroup"] = $spWeb.AssociatedMemberGroup.ID.ToString();
		$spWeb.Properties.Update();
		$spWeb.Update(); 
	}

}

function NeedConfigureDefaultGroups([string]$WebUrl)
{
	$SPWeb = Get-SPWeb $WebUrl;

	#$AssociatedVisitorGroupAppName = "Visitantes do " + $SPWeb.Title
	#$AssociatedOwnerGroupAppName = "Proprietários do " + $SPWeb.Title
	#$AssociatedMemberGroupAppName  = "Membros do " + $SPWeb.Title
	$AssociatedVisitorGroupAppName = $SPWeb.Title + " Visitors"
	$AssociatedOwnerGroupAppName = $SPWeb.Title + " Owners"
	$AssociatedMemberGroupAppName  = $SPWeb.Title + " Members"
	 

	if (((IsGroupExists $WebUrl $AssociatedVisitorGroupAppName) -eq $false) -and ((IsGroupExists $WebUrl $AssociatedOwnerGroupAppName) -eq $false) -and ((IsGroupExists $WebUrl $AssociatedMemberGroupAppName) -eq $false)) {
		return $true;
	}
	else {
		return $false;
	}

}

function IsPermissionLevelExists([string]$WebUrl, [string]$PermissionLevelName)
{
	$SPWeb = Get-SPWeb $WebUrl;
	$SPRoleDefinition = $SPWeb.RoleDefinitions | Where-Object { $_.name -eq $PermissionLevelName}

	if ($SPRoleDefinition -ne $null) {return $true;} else{return $false;}
}

function IsParserEnabled([string]$WebUrl)
{
	$web = Get-SPWeb $WebUrl;
	return $web.ParserEnabled;
}

function ConfigParseEnabled([string]$WebUrl, [Boolean] $ParseEnabled)
{
	$web = Get-SPWeb $WebUrl;
	$web.ParserEnabled = $ParseEnabled;
	$web.Update();
}

function CreatePermissionLevel([string]$WebUrl, [string]$PermissionLevelName, [string]$PermissionLevelDescription, [string]$PermissionLevelPermissions)
{
	$SPWeb = Get-SPWeb $WebUrl;
	
	$SPRoleDefinition = New-Object Microsoft.SharePoint.SPRoleDefinition;
	$SPRoleDefinition.Name = $PermissionLevelName;
	$SPRoleDefinition.Description = $PermissionLevelDescription;
	$SPRoleDefinition.BasePermissions = $PermissionLevelPermissions;

	$SPWeb.RoleDefinitions.Add($SPRoleDefinition);
	
	$SPWeb.Update();
}

function IsGroupExists([string]$WebUrl, [string]$GroupName)
{
	$SPWeb = Get-SPWeb $WebUrl;
	$SPGroup = $SPWeb.SiteGroups[$GroupName];

	if ($SPGroup -ne $null) {return $true;} else{return $false;}
}

function CreateSiteGroup([string]$WebUrl, [string]$GroupName, [string]$GroupDescription)
{
	$SPWeb = Get-SPWeb $WebUrl;
	$SPWeb.SiteGroups.Add($GroupName, $spWeb.Site.Owner, $spWeb.Site.Owner, $GroupDescription)
	$SPWeb.Update();
}

function IsUserMember([string]$WebUrl, [string]$GroupName, [string]$NetworkUserOrGroupLogin)
{
	$SPWeb = Get-SPWeb $WebUrl;
	$SPGroup = $SPWeb.SiteGroups[$GroupName];
	
	$Temp = $SPGroup.Users | Where-Object {$_.LoginName -eq $NetworkUserOrGroupLogin};
	if ($Temp -ne $null) {return $true;} else{return $false;}
}

function AddUserToSiteGroup([string]$WebUrl, [string]$GroupName, [string]$NetworkUserOrGroupLogin)
{

	$SPWeb = Get-SPWeb $WebUrl;
	$SPGroup = $SPWeb.SiteGroups[$GroupName];
	$SPUser = $SPWeb.EnsureUser($NetworkUserOrGroupLogin);

	if(($SPGroup -ne $null) -and ($SPUser -ne $null)){ 
		$SPGroup.Users.Add($SPUser.LoginName,$SPUser.Email,$SPUser.Name,"");
	}
}

function SiteFeatureIsActivated([string]$SiteCollectionUrl, [string]$BuiltInSiteFeatureId)
{
	$Temp = Get-SPFeature –Limit "All" -Site $SiteCollectionUrl | Where-Object {$_.Id -eq $BuiltInSiteFeatureId};
	if ($Temp -ne $null) {return $true;} else{return $false;}
}

function ActivateSiteFeature([string]$SiteCollectionUrl, [string]$BuiltInSiteFeatureId)
{
	Enable-SPFeature $BuiltInSiteFeatureId -Url $SiteCollectionUrl -Force:$true;
}

function DeactivateSiteFeature([string]$SiteCollectionUrl, [string]$BuiltInSiteFeatureId)
{
	Disable-SPFeature $BuiltInSiteFeatureId -Url $SiteCollectionUrl -Confirm:$false;
}

function WebSiteFeatureIsActivated([string]$WebSiteUrl, [string]$BuiltInWebSiteFeatureId, [string]$Scope)
{
	if ($Scope -eq "Site") {
		$Temp = Get-SPFeature –Limit "All" -Site $WebSiteUrl | Where-Object {$_.Id -eq $BuiltInWebSiteFeatureId};
	}
	else {
		$Temp = Get-SPFeature –Limit "All" -Web $WebSiteUrl | Where-Object {$_.Id -eq $BuiltInWebSiteFeatureId};
	}
	if ($Temp -ne $null) {return $true;} else{return $false;}
}

function ActivateWebSiteFeature([string]$WebSiteUrl, [string]$BuiltInWebSiteFeatureId)
{
	Enable-SPFeature $BuiltInWebSiteFeatureId -Url $WebSiteUrl -Force:$true;
}

function DeactivateWebSiteFeature([string]$WebSiteUrl, [string]$BuiltInWebSiteFeatureId)
{
	Disable-SPFeature $BuiltInWebSiteFeatureId -Url $WebSiteUrl -Confirm:$false;
}

function SandboxSolutionIsInstalled([string]$SiteCollectionURL, [string]$SandboxSolutionWSPName)
{
	$Temp = Get-SPUserSolution -Site $SiteCollectionURL | Where-Object {$_.Name -eq $SandboxSolutionWSPName -and $_.Status -eq "Activated"};
	if ($Temp -ne $null) {return $true;} else{return $false;}
}

function SandboxSolutionIsExists([string]$SiteCollectionURL, [string]$SandboxSolutionWSPName)
{
	$Temp = Get-SPUserSolution -Site $SiteCollectionURL | Where-Object {$_.Name -eq $SandboxSolutionWSPName};
	if ($Temp -ne $null) {return $true;} else{return $false;}
}

function UnInstallSandboxSolution([string]$SiteCollectionURL, [string]$SandboxSolutionWSPName)
{
	if ((SandboxSolutionIsInstalled $SiteCollectionURL $SandboxSolutionWSPName) -eq $true) {
		Uninstall-SPUserSolution –Identity $SandboxSolutionWSPName –Site $SiteCollectionURL -Confirm:$false;
	}
		Remove-SPUserSolution –Identity $SandboxSolutionWSPName –Site $SiteCollectionURL -Confirm:$false;
}

function InstallSandboxSolution([string]$SiteCollectionURL, [string]$SandboxSolutionWSPName)
{
		$Location = Get-Location;		

		#MSOCAF FOLDER STRUCTURE
		if($Location.Path.Contains("Installation scripts"))
		{
			cd..			
			Push-Location -Path "Solutions artifacts";	
			$Location = Get-Location;
			Pop-Location;
			Push-Location -Path "Installation scripts";
			$SandboxSolutionWSPPath = $Location.Path  + "\" + $SandboxSolutionWSPName;
		}
		else{
			$SandboxSolutionWSPPath = $Location.Path + "\UserSolutions\" + $SandboxSolutionWSPName;
		}
		
		Add-SPUserSolution -LiteralPath "$SandboxSolutionWSPPath" -Site $SiteCollectionURL;
		$SPUserSolution = Install-SPUserSolution –Identity $SandboxSolutionWSPName –Site $SiteCollectionURL -Confirm:$false;
}

function WebSiteExists([string]$SiteCollectionUrl, [string]$SiteUrl)
{
	$SPSite = Get-SPSite $SiteCollectionUrl;
	$Temp = $SPSite.AllWebs | Where-Object {$_.Url -eq $SiteUrl}

	if ($Temp -ne $null) {return $true;} else{return $false;}
}

function CreateWebSite([string]$WebSiteURL, [string]$WebSiteName, [Int32]$WebSiteLanguage, [string]$WebSiteTemplate, [string]$WebSiteDescription)
{
	$SPWebTemplate = Get-SPWebTemplate |  Where-Object {$_.Title -eq $WebSiteTemplate};

	$SPWeb = New-SPWeb $WebSiteURL -Name "$WebSiteName" -Template $SPWebTemplate.Name -Language $WebSiteLanguage -Description "$WebSiteDescription";
}

function ManagedPathExists([string]$WebApplicationUrl, [string]$ManagedPathUrl)
{
	if ($ManagedPathUrl.StartsWith("/")) {
		$SPManagedPath = Get-SPManagedPath -WebApplication $WebApplicationUrl | Where-Object {$_.name -eq $ManagedPathUrl.Substring(1,$ManagedPathUrl.Length-1) }
	}
	else {
		$SPManagedPath = Get-SPManagedPath -WebApplication $WebApplicationUrl | Where-Object {$_.name -eq $ManagedPathUrl}
	}

	if ($SPManagedPath -ne $null) {return $true;} else{return $false;}
}

function CreateManagedPath([string]$WebApplicationUrl, [string]$ManagedPathUrl, [bool]$Explicit)
{
	$SPManagedPath = New-SPManagedPath $ManagedPathUrl -WebApplication $WebApplicationUrl -Explicit:$Explicit ;
}

function DropManagedPath([string]$WebApplicationUrl, [string]$ManagedPathUrl)
{
	Remove-SPManagedPath $ManagedPathUrl -WebApplication $WebApplicationUrl –confirm:$false;
}

function EnumarateSiteCollectionsInManagedPath([string]$WebApplicationUrl, [string]$ManagedPathUrl)
{
	return Get-SPSite -Limit All | Where-Object {$_.Url.ToString().StartsWith($WebApplicationUrl + $ManagedPathUrl) -eq $true};
}

function DropWebSite([string]$WebSiteUrl)
{
	$SPWeb = Get-SPWeb $WebSiteUrl;
	
	if ($SPWeb.IsRootWeb -eq $false) {
		$SPWeb.Delete();
	}
	else
	{
		DropSiteCollection $WebSiteUrl;
	}
		
}

function FarmSolutionIsInstalled([string]$FarmSolutionWSPName)
{
	$Temp = Get-SPSolution | Where-Object {$_.Name -eq $FarmSolutionWSPName}
	if ($Temp -ne $null) {return $true;} else{return $false;}
}

function UnInstallFarmSolution([string]$FarmSolutionWSPName)
{
		$SPSolution = Get-SPSolution | Where-Object {$_.Name -eq $FarmSolutionWSPName}
		if ($SPSolution -ne $null)
		{
			if ($SPSolution.Deployed -eq $true)
			{
				if ($SPSolution.ContainsWebApplicationResource) {
					Uninstall-SPSolution –Identity $SPSolution -Confirm:$false -AllWebApplications:$true
				}
				else {
					Uninstall-SPSolution –Identity $SPSolution -Confirm:$false
				}
				
				WaitForJobToFinish 

 			}

			Remove-SPSolution –Identity $SPSolution -Confirm:$false
		}
}

function InstallGlobalFarmSolution([string]$FarmSolutionWSPName)
{
		InstallFarmSolution $FarmSolutionWSPName;
		
		$SPSolution = Get-SPSolution | Where-Object {$_.Name -eq $FarmSolutionWSPName};

		Install-SPSolution –Identity $SPSolution -Confirm:$false -GACDeployment:$true -Force:$true;
		
		WaitForJobToFinish;
}

function InstallFarmSolution([string]$FarmSolutionWSPName)
{
		$Location = Get-Location;		

		#MSOCAF FOLDER STRUCTURE
		if($Location.Path.Contains("Installation scripts"))
		{
			cd..			
			Push-Location -Path "Solutions artifacts";	
			$Location = Get-Location;
			Pop-Location;
			Push-Location -Path "Installation scripts";
			$FarmSolutionWSPPath = $Location.Path  + "\" + $FarmSolutionWSPName;
		}
		else{
			$FarmSolutionWSPPath = $Location.Path + "\FarmSolutions\" + $FarmSolutionWSPName;
		}
		$SPSolution = Add-SPSolution -LiteralPath "$FarmSolutionWSPPath";
}


function FarmSolutionIsDeployed([string]$FarmSolutionWSPName, [string]$WebApplicationURL)
{

	$SPSolution = Get-SPSolution | Where-Object {$_.Name -eq $FarmSolutionWSPName}
	
	if ($SPSolution.ContainsWebApplicationResource) {
		if ($WebApplicationURL.EndsWith("/") -eq $false) {
			$WebApplicationURL += "/"
		};
		$Temp = $SPSolution.DeployedWebApplications | Where-Object {$_.Url -eq $WebApplicationURL}
		if ($Temp -ne $null) {return $true;} else{return $false;}
	}
	else
	{
		return $SPSolution.Deployed;
	}
	

}

function DeployWebApplicationFarmSolution([string]$FarmSolutionWSPName, [string]$WebApplicationURL, [bool]$GACDeployment)
{
		$SPSolution = Get-SPSolution | Where-Object {$_.Name -eq $FarmSolutionWSPName};
		
		$SPWebApplication = Get-SPWebApplication $WebApplicationURL;

		if ($SPSolution.ContainsWebApplicationResource) {
			Install-SPSolution –Identity $SPSolution -Confirm:$false -GACDeployment:$GACDeployment -WebApplication $SPWebApplication -Force:$true;
		}
		else
		{
			Install-SPSolution –Identity $SPSolution -Confirm:$false -GACDeployment:$true -Force:$true;
		}
		
		WaitForJobToFinish;
		
		$Count  = 1
		do {
			WriteMessage $false $true "Retrying the Farm Soluion Deploy (Retry $Count/5)."
			DeployWebApplicationFarmSolutionInAnotherProcess $FarmSolutionWSPName $WebApplicationURL $GACDeployment;
			$Count++;
		} while (((FarmSolutionIsDeployed $FarmSolutionWSPName $WebApplicationURL) -eq $false) -and ($Count -le 5))
}

function DeployWebApplicationFarmSolutionInAnotherProcess([string]$FarmSolutionWSPName, [string]$WebApplicationURL, [bool]$GACDeployment)
{
	$Location = Get-Location;

	$Wscript = New-Object -Com Wscript.Shell;
	$Command = "powershell.exe -version 2.0 & '$Location\DeployWebApplicationFarmSolution.ps1' -FarmSolutionWSPName '$FarmSolutionWSPName' -WebApplicationURL '$WebApplicationURL' -GACDeployment '$GACDeployment'";
	$Result = $Wscript.Exec($command);
  
  	if ($Result.ExitCode -ne 0){
 		$Result.StdOut.ReadAll();
	}
}

function NetWorkUserOrGroupExists([string] $NetworkUserOrGroupLogin)
{
	$ct = [System.DirectoryServices.AccountManagement.ContextType]::Domain;           
	$user = [System.DirectoryServices.AccountManagement.Principal]::FindByIdentity($ct,$NetworkUserOrGroupLogin);
	if($user -ne $null) {return true;}
	return false;
	
}

function IsSiteCollectionAdmin([string]$SiteCollectionURL, [string] $NetworkUserOrGroupLogin)
{

	$SPUser = Get-SPUser -Web  $SiteCollectionURL | Where-Object {$_.UserLogin -eq $NetworkUserOrGroupLogin}

	if ($SPUser -ne $null) {
		return $SPUser.IsSiteAdmin;
	}
	
	return $false;
}
function AddSiteCollectionAdmin([string]$SiteCollectionURL, [string] $NetworkUserOrGroupLogin)
{
	$SPUser = Get-SPUser -Web  $SiteCollectionURL | Where-Object {$_.UserLogin -eq $NetworkUserOrGroupLogin}
	
	if ($SPUser -eq $null) {
		$SPUser = New-SPUser -UserAlias $NetworkUserOrGroupLogin -Web $SiteCollectionURL
	}
	
	Set-SPUser $SPUser -IsSiteCollectionAdmin:$true;
}

function ActivateFeatureInAnotherProcess([string] $URL, [string]$FeatureID)
{
	WriteMessage $false $true 'The activation will have a long delay to ensure the sucess.'
	powershell.exe -version 2.0 -noprofile -command "Add-PSSnapin 'Microsoft.SharePoint.PowerShell';Enable-SPFeature $FeatureID -Url $URL -Force:`$true; exit 0"
}

function DeactivateFeatureInAnotherProcess([string] $URL, [string]$FeatureID)
{
	WriteMessage $false $true 'The deactivation will have a long delay to ensure the sucess.'
	powershell.exe -version 2.0 -noprofile -command "Add-PSSnapin 'Microsoft.SharePoint.PowerShell';Disable-SPFeature $FeatureID -Url $URL; exit 0"
}

function FarmFeatureIsActivated([string]$FeatureId)
{
	$Temp = Get-SPFeature –Limit "All" -Farm | Where-Object {$_.Id -eq $FeatureId};
	if ($Temp -ne $null) {return $true;} else{return $false;}
}

function ActivateFarmFeature([string]$FeatureId)
{
	Enable-SPFeature $FeatureId -Force:$true;
}

function DeactivateFarmFeature([string]$FeatureId)
{
	Disable-SPFeature $FeatureId -Confirm:$false;
}

function ActivateFarmFeatureInAnotherProcess([string]$FeatureID)
{
	WriteMessage $false $true 'The activation will have a long delay to ensure the sucess.'
	powershell.exe -version 2.0 -noprofile -command "Add-PSSnapin 'Microsoft.SharePoint.PowerShell';Enable-SPFeature $FeatureID -Force:`$true; exit 0"
}

function DeactivateFarmFeatureInAnotherProcess([string]$FeatureID)
{
	WriteMessage $false $true 'The deactivation will have a long delay to ensure the sucess.'
	powershell.exe -version 2.0 -noprofile -command "Add-PSSnapin 'Microsoft.SharePoint.PowerShell';Disable-SPFeature $FeatureID -Confirm:`$false; exit 0"
}



function GetHostSiteCollection($HostWebApplication, [string]$SiteCollectionName )
{
	$Found = $false;
	
	foreach($HostSiteCollection in $HostWebApplication.SiteCollections.SiteCollection) {
					
		if ($HostSiteCollection.Name.toString().toLower() -eq $SiteCollectionName.toString().toLower()) {
			$Found = $true;
			break;
		}
	}
	
	if ($Found) {
		return $HostSiteCollection;
	}
	else {
		return $null;
	}
}

function GetHostWebApplication([string]$WebApplicationName)
{
	$Found = $false;
	$WebApplicationURL = $null;
	$hostname = hostname;
	
	foreach($ComputerHost in $HostedApplications) {
	
		$ComputerHostName = $ComputerHost.ComputerName;
		
		if ($ComputerHostName.toString().toLower() -eq $hostname.toString().toLower()) {
		
			foreach($HostWebApplication in $ComputerHost.WebApplications.WebApplication) {
						
				if ($HostWebApplication.Name.toString().toLower() -eq $WebApplicationName.toString().toLower()) {
					$Found = $true;
					break;
				}
			}
			
			break;
		}
	}
	
	
	if ($Found) {
		return $HostWebApplication;
	}
	else {
		return $null;
	}

}

function WebConfigModificationExists ([string]$WebApplicationURL, [string]$WebConfigModificationOwner, [string]$WebConfigModificationName)
{
	
	$SPWebApplication = [Microsoft.SharePoint.Administration.SPWebApplication]::Lookup($WebApplicationURL);
	$WebConfigModifications = @();
	$SPWebApplication.WebConfigModifications | where-object { ($_.Owner -eq $WebConfigModificationOwner) -and ($_.Name -eq $WebConfigModificationName) } | foreach-object { $WebConfigModifications = $WebConfigModifications + $_};

	if ($WebConfigModifications.Count -gt 0) {
		return $true;
	}
	else {
		return $false;
	}

}

function UninstallWebConfigModification([string]$WebApplicationURL, [string]$WebConfigModificationOwner, [string]$WebConfigModificationName)
{
	$SPWebApplication = [Microsoft.SharePoint.Administration.SPWebApplication]::Lookup($WebApplicationURL);
	$SPWebService = @($SPWebApplication.Farm.Services | where-object { $_.TypeName -eq "Microsoft SharePoint Foundation Web Application" } )[0]
	
	$WebConfigModifications = @();
	$SPWebApplication.WebConfigModifications | where-object { ($_.Owner -eq $WebConfigModificationOwner) -and ($_.Name -eq $WebConfigModificationName) } | foreach-object { $WebConfigModifications = $WebConfigModifications + $_};

	$WebConfigModifications | foreach-object{ $SPWebApplication.WebConfigModifications.Remove($_) | out-null };

	$SPWebApplication.Update();
	$SPWebService.ApplyWebConfigModifications();
}

function InstallWebConfigModification([string]$WebApplicationURL, [int]$WebConfigModificationType, [string]$WebConfigModificationOwner, [string]$WebConfigModificationPath, [string]$WebConfigModificationName, [string]$WebConfigModificationValue)
{
	$SPWebApplication = [Microsoft.SharePoint.Administration.SPWebApplication]::Lookup($WebApplicationURL);
	$SPWebService = @($SPWebApplication.Farm.Services | where-object { $_.TypeName -eq "Microsoft SharePoint Foundation Web Application" } )[0]
	
	$SPWebConfigModification = new-object "Microsoft.SharePoint.Administration.SPWebConfigModification";
	$SPWebConfigModification.Path = $WebConfigModificationPath;
	$SPWebConfigModification.Name = $WebConfigModificationName;
	$SPWebConfigModification.Sequence = 0;
	$SPWebConfigModification.Owner = $WebConfigModificationOwner;
	$SPWebConfigModification.Type = $WebConfigModificationType;
	$SPWebConfigModification.Value = $WebConfigModificationValue;

	$SPWebApplication.WebConfigModifications.Add($SPWebConfigModification);
	$SPWebApplication.Update();
	$SPWebService.ApplyWebConfigModifications();
}

function GetTokenValue([string]$WebSiteUrl, [string]$Value) {
	
	$ValueTemp = $Value;
	
	if ($ValueTemp.indexOf("WebApplications[") -gt -1) {
	
        [System.Text.RegularExpressions.MatchCollection] $HostWebApplicationMatchs = [Regex]::Matches($ValueTemp, "(?<=WebApplications\[).*?(?=\])");

        while ($HostWebApplicationMatchs -ne $null)
        {
			[System.String] $HostWebApplicationMatch = $HostWebApplicationMatchs[0].ToString();
			
			$PropertyHostWebApplication = GetHostWebApplication $HostWebApplicationMatch;
			
			if ($PropertyHostWebApplication -ne $null) {
			
				if ($ValueTemp.indexOf("WebApplications[" + $HostWebApplicationMatch + "].Url") -gt -1) {
					$ValueTemp = $ValueTemp.Replace("WebApplications[" + $HostWebApplicationMatch + "].Url", $PropertyHostWebApplication.URL.ToLower());
				}
				elseif ($ValueTemp.indexOf("WebApplications[" + $HostWebApplicationMatch + "].ID") -gt -1){	
			
					[Microsoft.Sharepoint.Administration.SPWebApplication] $SPWebApplication = [Microsoft.Sharepoint.Administration.SPWebApplication]::Lookup($PropertyHostWebApplication.URL);
					
					if ($SPWebApplication -ne $null) {
						[Guid] $Guid = $SPWebApplication.ID;
						$ValueTemp = $ValueTemp.Replace("WebApplications[" + $HostWebApplicationMatch + "].ID", $Guid.ToString() );
					}
				}
				else {
					[System.Text.RegularExpressions.MatchCollection] $HostSiteCollectionMatchs = [Regex]::Matches($ValueTemp, "(?<=WebApplications\[" + $HostWebApplicationMatch + "\]\.SiteCollections\[).*?(?=\])");
					[System.String] $HostSiteCollectionMatch = $HostSiteCollectionMatchs[0].ToString();
					$PropertyHostSiteCollection = GetHostSiteCollection $PropertyHostWebApplication $HostSiteCollectionMatch;
					
					$PropertySiteCollectionManagedPathUrl =  $PropertyHostSiteCollection.ManagedPathUrl;
					$PropertySiteCollectionRelativeURL = ($PropertySiteCollectionManagedPathUrl + $PropertyHostSiteCollection.URL).ToLower();
					$PropertySiteCollectionURL = ($PropertyHostWebApplication.URL + $PropertySiteCollectionManagedPathUrl + $PropertyHostSiteCollection.URL).ToLower();
							
					if ($ValueTemp.indexOf("WebApplications[" + $HostWebApplicationMatch + "].SiteCollections[" + $HostSiteCollectionMatch + "].Url") -gt -1) {
						$ValueTemp = $ValueTemp.Replace("WebApplications[" + $HostWebApplicationMatch + "].SiteCollections[" + $HostSiteCollectionMatch + "].Url", $PropertySiteCollectionURL);
					}
					elseif ($ValueTemp.indexOf("WebApplications[" + $HostWebApplicationMatch + "].SiteCollections[" + $HostSiteCollectionMatch + "].ServerRelativeUrl") -gt -1) {
						$ValueTemp = $ValueTemp.Replace("WebApplications[" + $HostWebApplicationMatch + "].SiteCollections[" + $HostSiteCollectionMatch + "].ServerRelativeUrl", $PropertySiteCollectionRelativeURL);
					}
					else {
						[System.Text.RegularExpressions.MatchCollection] $ListMatchs = [Regex]::Matches($ValueTemp, "(?<=WebApplications\[" + $HostWebApplicationMatch + "\]\.SiteCollections\[" + $HostSiteCollectionMatch + "\]\.Lists\[).*?(?=\])");
											
						[System.String] $ListMatch = $ListMatchs[0].ToString();
						
						[Microsoft.SharePoint.SPWeb] $SPWeb = Get-SPWeb $PropertySiteCollectionURL;
						[Microsoft.SharePoint.SPList] $SPList = $SPWeb.Lists.TryGetList($ListMatch);
						
						$ValueTemp = $ValueTemp.Replace("WebApplications[" + $HostWebApplicationMatch + "].SiteCollections[" + $HostSiteCollectionMatch + "].Lists[" + $ListMatch + "].ID", $SPList.ID.ToString());
		
						$SPWeb.Close();
						$SPWeb.Dispose();
					}
				}
						
				$HostWebApplicationMatchs = [Regex]::Matches($ValueTemp, "(?<=WebApplications\[).*?(?=\])");
	        }
			else {
				$HostWebApplicationMatchs = $null;
				$ValueTemp = $null;
			}
		}
	}
	
	if (($ValueTemp -ne $null) -and ($ValueTemp.indexOf("URLEncode[") -gt -1)) {
	
        [System.Text.RegularExpressions.MatchCollection] $URLEncodeMatchs = [Regex]::Matches($ValueTemp, "(?<=URLEncode\[).*?(?=\])");

        while ($URLEncodeMatchs -ne $nul)
        {
			[System.String] $URLEncodeMatch = $URLEncodeMatchs[0].ToString();
						
			if ($ValueTemp.indexOf("URLEncode[" + $URLEncodeMatch + "]") -gt -1) {
				$ValueTemp = $ValueTemp.Replace("URLEncode[" + $URLEncodeMatch + "]", [Microsoft.SharePoint.Utilities.SPEncode]::UrlEncode($URLEncodeMatch));
			}
			$URLEncodeMatchs = [Regex]::Matches($ValueTemp, "(?<=URLEncode\[).*?(?=\])");
        }
	}
		
	return $ValueTemp;

}


function SetSiteProperty([string]$WebSiteUrl, [string]$SitePropertyName, [string]$SitePropertyValue)
{
	[Microsoft.SharePoint.SPWeb] $SPWeb = Get-SPWeb $WebSiteUrl;
	
	if ($SitePropertyValue.indexOf("WebApplications[") -gt -1) {
	
        [System.Text.RegularExpressions.MatchCollection] $HostWebApplicationMatchs = [Regex]::Matches($SitePropertyValue, "(?<=WebApplications\[).*?(?=\])");

		[System.String] $SitePropertyValueTemp = $SitePropertyValue;
        while ($HostWebApplicationMatchs -ne $nul)
        {
			[System.String] $HostWebApplicationMatch = $HostWebApplicationMatchs[0].ToString();
			
			$PropertyHostWebApplication = GetHostWebApplication $HostWebApplicationMatch;
			
			if ($SitePropertyValueTemp.indexOf("WebApplications[" + $HostWebApplicationMatch + "].Url") -gt -1) {
				$SitePropertyValueTemp.Replace("WebApplications[" + $HostWebApplicationMatch + "].Url", $PropertyHostWebApplication.URL);
			}
			else {
				[System.Text.RegularExpressions.MatchCollection] $HostSiteCollectionMatchs = [Regex]::Matches($SitePropertyValue, "(?<=WebApplications\[" + $HostWebApplicationMatch + "\]\.SiteCollections\[).*?(?=\])");
				[System.String] $HostSiteCollectionMatch = $HostSiteCollectionMatchs[0].ToString();
				$PropertyHostSiteCollection = GetHostSiteCollection $PropertyHostWebApplication $HostSiteCollectionMatch;
				
				$PropertySiteCollectionManagedPathUrl =  $PropertyHostSiteCollection.ManagedPathUrl;
				$PropertySiteCollectionURL =  $PropertyHostWebApplication.URL + $PropertySiteCollectionManagedPathUrl + $PropertyHostSiteCollection.URL;
			
				$SitePropertyValueTemp = $SitePropertyValueTemp.Replace("WebApplications[" + $HostWebApplicationMatch + "].SiteCollections[" + $HostSiteCollectionMatch + "].Url", $PropertySiteCollectionURL);
			}
					
			$HostWebApplicationMatchs = [Regex]::Matches($SitePropertyValue, "(?<=\WebApplications\[).*?(?=\])");
        }
		
		if ($SPWeb.AllProperties[$SitePropertyName] -eq $null) {
			WriteMessage $false $true "Setting Property $SitePropertyName with value $SitePropertyValueTemp to $WebSiteUrl."
			$SPWeb.AllProperties.Add($SitePropertyName,$SitePropertyValueTemp);
		}
		else {
			if ($SPWeb.AllProperties[$SitePropertyName] -ne $SitePropertyValueTemp) {
				WriteMessage $false $true "Setting Property $SitePropertyName with value $SitePropertyValueTemp to $WebSiteUrl."
				$SPWeb.AllProperties[$SitePropertyName] = $SitePropertyValueTemp;
			}
		}
	}
	else {
		if ($SPWeb.AllProperties[$SitePropertyName] -eq $null) {
			WriteMessage $false $true "Setting Property $SitePropertyName with value $SitePropertyValue to $WebSiteUrl."
			$SPWeb.AllProperties.Add($SitePropertyName,$SitePropertyValue);
		}
		else {
			if ($SPWeb.AllProperties[$SitePropertyName] -ne $SitePropertyValue) {
				WriteMessage $false $true "Setting Property $SitePropertyName with value $SitePropertyValue to $WebSiteUrl."
				$SPWeb.AllProperties[$SitePropertyName] = $SitePropertyValue;
			}
		}
	}

	$SPWeb.Update();	
	$SPWeb.Close();
	$SPWeb.Dispose();
}

function SetupMaster([string]$WebSiteUrl, [string]$MasterName, [string]$CustomMasterName, [bool]$MasterInherit, [string]$MasterForceAllSubWebInherit, [bool]$CustomMasterInherit, [string]$CustomMasterForceAllSubWebInherit) {

	[Microsoft.SharePoint.SPWeb] $SPWeb = Get-SPWeb $WebSiteUrl;
	[Microsoft.SharePoint.Publishing.PublishingWeb] $PublishingWeb = [Microsoft.SharePoint.Publishing.PublishingWeb]::GetPublishingWeb($SPWeb);

	[string] $SiteUrl = $null;
	
	if ($PublishingWeb.Web.ServerRelativeUrl.EndsWith("/")) {
	
		$SiteUrl = $PublishingWeb.Web.ServerRelativeUrl;
		
	} else {
	
		$SiteUrl =  $PublishingWeb.Web.ServerRelativeUrl + "/";
	}

	[string] $MasterUrl = $SiteUrl + "_catalogs/masterpage/$MasterName"
	[string] $CustomMasterUrl = $SiteUrl + "_catalogs/masterpage/$MasterName"

	$PublishingWeb.MasterUrl.SetValue($MasterUrl) | out-null;
	$PublishingWeb.CustomMasterUrl.SetValue($CustomMasterUrl) | out-null;
	
	$PublishingWeb.MasterUrl.SetInherit($MasterInherit, $MasterForceAllSubWebInherit) | out-null;
	$PublishingWeb.CustomMasterUrl.SetInherit($CustomMasterInherit, $CustomMasterForceAllSubWebInherit) | out-null;

	$PublishingWeb.Update();
	$PublishingWeb.Web.Update();
	$SPWeb.Close();
	$SPWeb.Dispose();
	
}

function SetupCSS([string]$WebSiteUrl, [string]$CSSName, [bool]$CSSInherit, [string]$CSSForceAllSubWebInherit) {

	[Microsoft.SharePoint.SPWeb] $SPWeb = Get-SPWeb $WebSiteUrl;
	[Microsoft.SharePoint.Publishing.PublishingWeb] $PublishingWeb = [Microsoft.SharePoint.Publishing.PublishingWeb]::GetPublishingWeb($SPWeb);

	[string] $SiteUrl = $null;
	
	if ($PublishingWeb.Web.ServerRelativeUrl.EndsWith("/")) {
	
		$SiteUrl = $PublishingWeb.Web.ServerRelativeUrl;
		
	} else {
	
		$SiteUrl =  $PublishingWeb.Web.ServerRelativeUrl + "/";
	}
	
	[string] $AlternateCssUrl = $SiteUrl + "Style%20Library/$CSSName";

	$PublishingWeb.AlternateCssUrl.SetValue($AlternateCssUrl) | out-null;
	$PublishingWeb.AlternateCssUrl.SetInherit($CSSInherit, $CSSForceAllSubWebInherit) | out-null;

	$PublishingWeb.Update();
	$PublishingWeb.Web.Update();
	$SPWeb.Close();
	$SPWeb.Dispose();
	
}

function SetupSiteLogo([string]$WebSiteUrl, [string]$SiteLogo, [string]$SiteLogoDescription) {

	[Microsoft.SharePoint.SPWeb] $SPWeb = Get-SPWeb $WebSiteUrl;
	[Microsoft.SharePoint.Publishing.PublishingWeb] $PublishingWeb = [Microsoft.SharePoint.Publishing.PublishingWeb]::GetPublishingWeb($SPWeb);

	[string] $SiteUrl = $null;	
	if ($PublishingWeb.Web.ServerRelativeUrl.EndsWith("/")) {
	
		$SiteUrl = $PublishingWeb.Web.Url;
		
	} else {
	
		$SiteUrl =  $PublishingWeb.Web.Url + "/";
	}
	
    $PublishingWeb.Web.SiteLogoUrl = $SiteUrl + "Style%20Library/images/" + $SiteLogo;
    $PublishingWeb.Web.SiteLogoDescription = $SiteLogoDescription;
	
	$PublishingWeb.Update();
	$PublishingWeb.Web.Update();
	$SPWeb.Close();
	$SPWeb.Dispose();
	
}

function PublishAndApproveFilesRecursiveWeb([string]$WebSiteUrl) {

	[Microsoft.SharePoint.SPWeb] $SPWeb = Get-SPWeb $WebSiteUrl;
				
	[Microsoft.SharePoint.SPList] $SPList = $null;

    foreach ($SPList in $SPWeb.Lists)
    {
        if ($SPList.BaseType -eq [Microsoft.SharePoint.SPBaseType]::DocumentLibrary)
        {
            if ($SPList.BaseTemplate -ne [Microsoft.SharePoint.SPListTemplateType]::MasterPageCatalog -or $SPWeb.IsRootWeb)
            {
                PublishAndApproveFilesRecursiveDocumentLibrary $SPList;
            }
        }
    }
	
	$SPWeb.Close();
	$SPWeb.Dispose();
	
}

function PublishAndApproveFilesRecursiveDocumentLibrary([Microsoft.SharePoint.SPDocumentLibrary] $SPDocumentLibrary) {

	if ($SPDocumentLibrary -ne $null) {
	
        if ($SPDocumentLibrary.EnableVersioning){
		
			for ($i = 0; $i -lt $SPDocumentLibrary.CheckedOutFiles.Count; $i++) {
			
				[Microsoft.SharePoint.SPCheckedOutFile] $SPCheckedOutFile = $SPDocumentLibrary.CheckedOutFiles[$i];
				
                $SPCheckedOutFile.TakeOverCheckOut();
                [Microsoft.SharePoint.SPListItem] $SPListItem = $SPDocumentLibrary.GetItemById($SPCheckedOutFile.ListItemId);
                ApproveFile $SPListItem.File;
		
			}

			PublishAndApproveFilesRecursiveFolder $SPDocumentLibrary.RootFolder;

        }
    }
}

function PublishAndApproveFilesRecursiveFolder([Microsoft.SharePoint.SPFolder] $SPFolder) {

    if ($SPFolder.Files -ne $null) {
		
		for ($i = 0; $i -lt $SPFolder.Files.Count; $i++) {
		
			[Microsoft.SharePoint.SPFile] $SPFile = $SPFolder.Files[$i];
			
            if ($SPFile.Item -ne $null) {
			
                ApproveFile $SPFile;
            }
		}
	}

    if ($SPFolder.SubFolders -ne $null) {
	
		for ($i = 0; $i -lt $SPFolder.SubFolders.Count; $i++) {
		
			[Microsoft.SharePoint.SPFolder] $SPSubFolder = $SPFolder.SubFolders[$i];
			
			PublishAndApproveFilesRecursiveFolder $SPSubFolder;
		}
	
    }
}

function InstanciateByCheckOutUser([Microsoft.SharePoint.SPListItem] $SPListItem) {

        [Microsoft.SharePoint.SPUserToken] $SPUserToken = $null;

        if ($SPListItem.File.CheckedOutByUser -ne $null) {
            $SPUserToken = $SPListItem.File.CheckedOutByUser.UserToken;
        }

        if ($SPListItem -ne $null)
        {
            [Microsoft.SharePoint.SPSite] $SPSite = New-Object Microsoft.SharePoint.SPSite($SPListItem.Web.Site.Url, $SPUserToken);
            [Microsoft.SharePoint.SPWeb] $SPWeb = $SPSite.OpenWeb($SPListItem.Web.ID);

            [Microsoft.SharePoint.SPList] $SPList = $SPWeb.Lists[$SPListItem.ParentList.ID];
            return $SPList.GetItemById($SPListItem.ID);

        }

        return $null;
}

function CheckInFile([Microsoft.SharePoint.SPFile] $SPFile, [Microsoft.SharePoint.SPCheckinType] $SPCheckinType) {

 	if ($SPFile.CheckOutType -ne 2) {
	
	    if ($SPFile.CheckedOutByUser.ID -ne $SPFile.Web.CurrentUser.ID)
	    {

	        //Trying method 1 to get the file Checked-in

	        [Microsoft.SharePoint.SPDocumentLibrary] $SPDocumentLibrary = $SPFile.$SPDocumentLibrary;

	        [Microsoft.SharePoint.SPCheckedOutFile] $SPCheckedOutFile = $SPDocumentLibrary.CheckedOutFiles.GetEnumerator() | Where-Object {$_.ListItemId -eq $SPFile.Item.ID};

	        if ($SPCheckedOutFile -ne $null)
	        {
	            $SPCheckedOutFile.TakeOverCheckOut();
	            [Microsoft.SharePoint.SPListItem] $SPListItem = $SPDocumentLibrary.GetItemById($SPCheckedOutFile.ListItemId);
	            $SPListItem.File.CheckIn([System.String]::Empty, $SPCheckinType);
	        }
	        else
	        {

	            //Trying method 2 to get the file Checked-in
	            [Microsoft.SharePoint.SPListItem] $SPListItem = InstanciateByCheckOutUser $SPFile.Item;
	             $SPListItem.File.CheckIn([System.String]::Empty, $SPCheckinType);

	            [Microsoft.SharePoint.SPWeb] $SPWeb = $SPListItem.Web;
	            [Microsoft.SharePoint.SPSite] $SPSite = $SPListItem.Web.Site;

	            $SPWeb.Close();
	            $SPWeb.Dispose();

				$SPSite.Close();
	            $SPSite.Dispose();
	        }
	    }
	    else
	    {
	        $SPFile.CheckIn([string]::Empty);
	    }
	}
}	

function PublishFile([Microsoft.SharePoint.SPFile] $SPFile) {

 	CheckInFile $SPFile 2 #[Microsoft.SharePoint.SPCheckinType]::MajorCheckIn;

	if ($SPFile.DocumentLibrary.EnableMinorVersions) {
	
		[Int32] $ErrorCount = 0;
		
	    while ($SPFile.Level -eq [Microsoft.SharePoint.SPFileLevel]::Draft) {
		
			try {
				$SPFile.Publish([string]::Empty);
				break;
			}
			catch {
			 
                 $ErrorCount += 1;

                 if ($ErrorCount -lt 3)
                 {
                     Start-Sleep -Milliseconds 100;
                 }
                 else
                 {
                     throw "Exception publishing file $SPFile.Url";
                 }
             }
	    }
	}
}

function ApproveFile([Microsoft.SharePoint.SPFile] $SPFile) {

    PublishFile $SPFile;
	
	[Microsoft.SharePoint.SPFile] $SPFile = $SPFile.Item.File;

    if ($SPFile.DocumentLibrary.EnableModeration) {

		[Int32] $ErrorCount = 0;

         while ($SPFile.Item.ModerationInformation.Status -eq [Microsoft.SharePoint.SPModerationStatusType]::Pending) {
             try {
			
        		$SPFile.Item.File.Approve([string]::Empty);
                break;
             }
             catch {
			 
                 $ErrorCount += 1;
				 
				 Write-Host $ErrorCount;

                 if ($ErrorCount -lt 3)
                 {
                     Start-Sleep -Milliseconds 100;
                 }
                 else
                 {
                     throw "Exception approving file $SPFile.Url";
                 }
             }
         }


	}
}

function SetUserCodeWebPartProperties ([string]$WebSiteURL, [string]$PageWebRelativeUrl, [string]$WebPartID, $PropertiesNamesArray, $PropertiesValuesArray)
{

	$SPWeb = Get-SPWeb $WebSiteURL;
	$SPFile = $SPWeb.GetFile($WebSiteUrl + $PageWebRelativeUrl);

	if ($SPFile.CheckOutType -eq 2) { 
		$SPFile.CheckOut();
	}
	
	#$SPLimitedWebPartManager = $SPFile.GetLimitedWebPartManager([System.Web.UI.WebControls.WebParts.PersonalizationScope]::Shared);
	$SPLimitedWebPartManager = $SPWeb.GetLimitedWebPartManager($WebSiteUrl + $PageWebRelativeUrl, [System.Web.UI.WebControls.WebParts.PersonalizationScope]::Shared);
	$SPWebPart = $SPLimitedWebPartManager.WebParts | Where-Object { $_.ID -eq $WebPartID };

	for ($i = 0; $i -lt $PropertiesNamesArray.Count; $i++) {
	
		[string] $PropertyName = $PropertiesNamesArray[$i];
		[string] $PropertyValue = $PropertiesValuesArray[$i];
		
		$SPWebPart.Properties[$PropertyName].value = $PropertyValue;

	}

	$SPLimitedWebPartManager.SaveChanges($SPWebPart);
	
	$SPFile.CheckIn([string]::Empty);

	$SPWeb.Close();
	$SPWeb.Dispose();
}

function ReplaceTextInFile ([string]$WebSiteURL, [string]$ReplaceFileRelativeUrl, [string]$FindText, [string]$ReplaceValue)
{
	[Microsoft.SharePoint.SPWeb] $SPWeb = Get-SPWeb $WebSiteUrl;
	
	[Microsoft.SharePoint.SPFile] $SPFile = $SPWeb.GetFile($WebSiteUrl + $ReplaceFileRelativeUrl);
	
 	if ($SPFile.CheckOutType -eq 2) { 
		$SPFile.CheckOut();
	}
	
	$Stream = $SPFile.OpenBinaryStream();

  	$StreamReader = New-Object System.IO.StreamReader($Stream);
	
	$NewContent = [Regex]::Replace($StreamReader.ReadToEnd(), $FindText, $ReplaceValue );
	
	$buffer = [System.Text.Encoding]::UTF8.GetBytes($NewContent);
	
	$MemoryStream = New-Object System.IO.MemoryStream($buffer,$true);
	
	$SPFile.SaveBinary($MemoryStream);
   
	$SPFile.CheckIn([string]::Empty);
	
	$StreamReader.Close();
	$StreamReader.Dispose();
	
	$Stream.Close();
	$Stream.Dispose();
	
	$SPWeb.Close();
	$SPWeb.Dispose();
}



function ProcessSites($WebSite, $WebSiteURL)
{
	#******************************************************************************************************************************
	# Processing Web Sites Groups
	#******************************************************************************************************************************
	
	if ($WebSite.Groups.Group -ne $null){
		foreach($Group in $WebSite.Groups.Group) {
							
			$GroupName = $Group.Name
			$GroupDescription = $Group.Description
							
			if ((IsGroupExists $WebSiteURL $GroupName) -eq $false){
				WriteMessage $false $true "Creting Group $GroupName inside $WebSiteURL."
				CreateSiteGroup $WebSiteURL $GroupName $GroupDescription;
			}
							
			foreach($NetworkUserOrGroup in $Group.NetworkUserOrGroups.NetworkUserOrGroup) {
								
				If (![String]::IsNullOrEmpty($NetworkUserOrGroup)){
					$NetworkUserOrGroupLogin =  $NetworkUserOrGroup.Login
								
if (NetWorkUserOrGroupExists $NetworkUserOrGroupLogin) {								
					if ((IsUserMember $WebSiteURL $GroupName $NetworkUserOrGroupLogin) -eq $false){
						WriteMessage $false $true "Adding User $NetworkUserOrGroupLogin to Group $GroupName inside $WebSiteURL."
						AddUserToSiteGroup $WebSiteURL $GroupName $NetworkUserOrGroupLogin;
					}
					
					}
							else {
								WriteMessage $false $true "Cannot find the Network User or Group $NetworkUserOrGroupLogin."
							}
				}
			}
		}
	}
		
	#******************************************************************************************************************************
	# Processing Web Sites Properties
	#******************************************************************************************************************************
	
	if ($WebSite.SiteProperties.SiteProperty -ne $null){
		foreach($SiteProperty in $WebSite.SiteProperties.SiteProperty) {
							
			$SitePropertyName = $SiteProperty.Name
			$SitePropertyValue = $SiteProperty.Value
							
			SetSiteProperty $WebSiteURL $SitePropertyName $SitePropertyValue;
		}
	}
					
	#******************************************************************************************************************************
	# Processing Web Site Internal Resources from all Web Sites
	#******************************************************************************************************************************

	if ($WebSite.BuiltInWebSiteFeatures.BuiltInWebSiteFeature -ne $null){
		foreach($BuiltInWebSiteFeature in $WebSite.BuiltInWebSiteFeatures.BuiltInWebSiteFeature) {
							
			$BuiltInWebSiteFeatureName =  $BuiltInWebSiteFeature.Name;
			$BuiltInWebSiteFeatureId =  $BuiltInWebSiteFeature.Id;
			$BuiltInWebSiteFeatureDeployMode =  $BuiltInWebSiteFeature.DeployMode;

			if ($BuiltInWebSiteFeatureDeployMode -eq "Activate") {

				if ((WebSiteFeatureIsActivated $WebSiteURL $BuiltInWebSiteFeatureId "Web") -eq $false){
					WriteMessage $false $true "Activating BultIn Web Site Feature $BuiltInWebSiteFeatureName inside $WebSiteURL."
					ActivateWebSiteFeature $WebSiteURL $BuiltInWebSiteFeatureId;
				}

			}
			elseif ($BuiltInWebSiteFeatureDeployMode -eq "Deactivate") {

				if ((WebSiteFeatureIsActivated $WebSiteURL $BuiltInWebSiteFeatureId "Web") -eq $true){
					WriteMessage $false $true "Deactivating BultIn Web Site Feature $BuiltInWebSiteFeatureName inside $WebSiteURL."
					DeactivateWebSiteFeature $WebSiteURL $BuiltInWebSiteFeatureId;
				}

			}
			elseif ($BuiltInWebSiteFeatureDeployMode -eq "Reactivate") {

				if ((WebSiteFeatureIsActivated $WebSiteURL $BuiltInWebSiteFeatureId "Web") -eq $true){
					WriteMessage $false $true "Deactivating BultIn Web Site Feature $BuiltInWebSiteFeatureName inside $WebSiteURL."
					DeactivateWebSiteFeature $WebSiteURL $BuiltInWebSiteFeatureId;
				}

				if ((WebSiteFeatureIsActivated $WebSiteURL $BuiltInWebSiteFeatureId "Web") -eq $false){
					WriteMessage $false $true "Activating BultIn Web Site Feature $BuiltInWebSiteFeatureName inside $WebSiteURL."
					ActivateWebSiteFeature $WebSiteURL $BuiltInWebSiteFeatureId;
				}

			}	
							
		}
	}
						
	#******************************************************************************************************************************
	# Processing Web Site User Solution Resources on Site Collection
	#******************************************************************************************************************************

	if ($WebSite.SandboxWebSiteFeatures.SandboxWebSiteFeature -ne $null){
		foreach($SandboxWebSiteFeature in $WebSite.SandboxWebSiteFeatures.SandboxWebSiteFeature) {
							
			$SandboxWebSiteFeatureName =  $SandboxWebSiteFeature.Name
			$SandboxWebSiteFeatureId =  $SandboxWebSiteFeature.Id
			$SandboxWebSiteFeatureDeployMode =  $SandboxWebSiteFeature.DeployMode

			if ($SandboxWebSiteFeatureDeployMode -eq "Activate") {

				if ((WebSiteFeatureIsActivated $WebSiteURL $SandboxWebSiteFeatureId "Web") -eq $false){
					WriteMessage $false $true "Activating Sandbox Web Site Feature $SandboxWebSiteFeatureName inside $WebSiteURL."
					ActivateWebSiteFeature $WebSiteURL $SandboxWebSiteFeatureId;
				}

			}
			elseif ($SandboxWebSiteFeatureDeployMode -eq "Deactivate") {

				if ((WebSiteFeatureIsActivated $WebSiteURL $SandboxWebSiteFeatureId "Web") -eq $true){
					WriteMessage $false $true "Deactivating Sandbox Web Site Feature $SandboxWebSiteFeatureName inside $WebSiteURL."
					DeactivateWebSiteFeature $WebSiteURL $SandboxWebSiteFeatureId;
				}

			}
			elseif ($SandboxWebSiteFeatureDeployMode -eq "Reactivate") {

				if ((WebSiteFeatureIsActivated $WebSiteURL $SandboxWebSiteFeatureId "Web") -eq $true){
					WriteMessage $false $true "Deactivating Sandbox Web Site Feature $SandboxWebSiteFeatureName inside $WebSiteURL."
					DeactivateWebSiteFeature $WebSiteURL $SandboxWebSiteFeatureId;
				}

				if ((WebSiteFeatureIsActivated $WebSiteURL $SandboxWebSiteFeatureId "Web") -eq $false){
					WriteMessage $false $true "Activating Sandbox Web Site Feature $SandboxWebSiteFeatureName inside $WebSiteURL."
					ActivateWebSiteFeature $WebSiteURL $SandboxWebSiteFeatureId;
				}

			}	
														
		}
	}
		
	#******************************************************************************************************************************
	# Processing Extended Actions
	#******************************************************************************************************************************
	
	if ($WebSite.WebSiteExtensionActions.WebSiteExtensionAction -ne $null){
		foreach($WebSiteExtensionAction in $WebSite.WebSiteExtensionActions.WebSiteExtensionAction) {
							
			$WebSiteExtensionActionAction = $WebSiteExtensionAction.Action;

			switch ($WebSiteExtensionActionAction) {
		
				"SetupMaster" {
					[string]$MasterName = $WebSiteExtensionAction.MasterName;
					[string]$CustomMasterName = $WebSiteExtensionAction.CustomMasterName;
					[bool]$MasterInherit = [System.Convert]::ToBoolean($WebSiteExtensionAction.MasterInherit);
					[bool]$MasterForceAllSubWebInherit = [System.Convert]::ToBoolean($WebSiteExtensionAction.MasterForceAllSubWebInherit);
					[bool]$CustomMasterInherit = [System.Convert]::ToBoolean($WebSiteExtensionAction.CustomMasterInherit);
					[bool]$CustomMasterForceAllSubWebInherit = [System.Convert]::ToBoolean($WebSiteExtensionAction.CustomMasterForceAllSubWebInherit);
					
					WriteMessage $false $true "Configuring MasterPage inside $WebSiteURL Site."
					SetupMaster $WebSiteURL $MasterName $CustomMasterName $MasterInherit $MasterForceAllSubWebInherit $CustomMasterInherit $CustomMasterForceAllSubWebInherit;
				}
				
				"SetupCSS" {
					[string]$CSSName = $WebSiteExtensionAction.CSSName;
					[bool]$CSSInherit = [System.Convert]::ToBoolean($WebSiteExtensionAction.CSSInherit);
					[bool]$CSSForceAllSubWebInherit = [System.Convert]::ToBoolean($WebSiteExtensionAction.CSSForceAllSubWebInherit);
				
					WriteMessage $false $true "Configuring CSS inside $WebSiteURL Site."
					SetupCSS $WebSiteURL $CSSName $CSSInherit $CSSForceAllSubWebInherit;
				}
				
				"SetupSiteLogo" {
					[string]$SiteLogoName = $WebSiteExtensionAction.SiteLogoName;
					[string]$SiteLogoDescription =  $WebSiteExtensionAction.SiteLogoDescription;
				
					WriteMessage $false $true "Configuring Site Logo inside $WebSiteURL Site."
					SetupSiteLogo $WebSiteURL $SiteLogoName $SiteLogoDescription;
				}
				
				"PublishAndApproveFilesRecursive" {
					WriteMessage $false $true "Publishing and Approving all Files inside $WebSiteURL Site."
					PublishAndApproveFilesRecursiveWeb $WebSiteURL;
				}
				
				"SetUserCodeWebPartProperties" {
					[string]$PageWebRelativeUrl = $WebSiteExtensionAction.PageWebRelativeUrl;
					[string]$WebPartID = $WebSiteExtensionAction.WebPartID;
					[string]$PropertiesNames = $WebSiteExtensionAction.PropertiesNamesArray;
					[string]$PropertiesValues = $WebSiteExtensionAction.PropertiesValuesArray;
					[char]$ArraySeparator = [System.Convert]::ToChar($WebSiteExtensionAction.ArraySeparator);
					
					$PropertiesNamesArray = $PropertiesNames.Split($ArraySeparator);
					$PropertiesValuesArray = $PropertiesValues.Split($ArraySeparator);
					
					$PropertiesValuesTokenArray = @();
					$PropertiesValuesArray | foreach-object { $PropertiesValuesTokenArray = $PropertiesValuesTokenArray + (GetTokenValue $WebSiteURL $_)};
					
					WriteMessage $false $true "Setting Properties for UserCodeWebPart $WebPartID in $PageWebRelativeUrl."
					SetUserCodeWebPartProperties $WebSiteURL $PageWebRelativeUrl $WebPartID $PropertiesNamesArray $PropertiesValuesTokenArray;
				}
				
				"ReplaceTextInFile" {
					[string]$FileRelativeUrl = $WebSiteExtensionAction.FileRelativeUrl;
					[string]$FindText = $WebSiteExtensionAction.FindText;
					[string]$ReplaceValue = $WebSiteExtensionAction.ReplaceValue;
					
					$ReplaceTokenValue = GetTokenValue $WebSiteURL $ReplaceValue;
					
					if ($ReplaceTokenValue -ne $null) {
						WriteMessage $false $true "Replacing $FindText to $ReplaceTokenValue in $FileRelativeUrl."
						ReplaceTextInFile $WebSiteURL $FileRelativeUrl $FindText $ReplaceTokenValue;
					}
					else {
						WriteMessage $false $true "Cannot Replace $FindText in $FileRelativeUrl."
					}
				}
			}
		}
	}
}

#******************************************************************************************************************************
# Load the deploy configuration
#****************************************************************************************************************************************

$MyPath = Split-Path $MyInvocation.MyCommand.Path
cd $MyPath;
$DeployXML = [xml] (Get-Content ($args[0]) -Encoding UTF8);
$HostedApplicationsXML = [xml] (Get-Content ("HostedApplications.xml") -Encoding UTF8);

$GlobalFarmSolutions = $DeployXML.Deploy.GlobalFarmSolutions.GlobalFarmSolution;
$ChainedFarmFeatures = $DeployXML.Deploy.ChainedFarmFeatures.ChainedFarmFeature;
$WebApplications = $DeployXML.Deploy.WebApplications.WebApplication;
$HostedApplications = $HostedApplicationsXML.Deploy.HostedApplications.ComputerHost;
[Microsoft.SharePoint.Administration.SPFarm]$farm = [Microsoft.SharePoint.Administration.SPFarm]::get_Local()

#******************************************************************************************************************************
# Processing Farm Global Solutions
#******************************************************************************************************************************

if ($GlobalFarmSolutions -ne $null){

	foreach($GlobalFarmSolution in $GlobalFarmSolutions) {
	
		$GlobalFarmSolutionName =  $GlobalFarmSolution.Name
		$GlobalFarmSolutionWSPName =  $GlobalFarmSolution.WSPName
		$GlobalFarmSolutionDeployMode =  $GlobalFarmSolution.DeployMode
		$GlobalFarmSolutionRestartUserCode =  [System.Convert]::ToBoolean($GlobalFarmSolution.RestartUserCode)
		
		if ([System.String]::IsNullOrEmpty($GlobalFarmSolution.RestartTimer) -eq $false) {
			$GlobalFarmSolutionRestartTimer =  [System.Convert]::ToBoolean($GlobalFarmSolution.RestartTimer);
		} else { $GlobalFarmSolutionRestartTimer = $null;}
		
		if ($GlobalFarmSolutionDeployMode -eq "Deploy"){
			
			if ((FarmSolutionIsInstalled $GlobalFarmSolutionWSPName) -eq $false){
			
				if ($GlobalFarmSolutionRestartUserCode -eq $true) {
					StopSharePointServicesInFarm $farm $sandboxServiceInstanceName $sandboxServiceName;
				}
				
				WriteMessage $false $true "Installing Global Farm Solution $GlobalFarmSolutionName."
				InstallGlobalFarmSolution $GlobalFarmSolutionWSPName;
				
				if ($GlobalFarmSolutionRestartUserCode -eq $true) {
					StartSharePointServicesInFarm $farm $sandboxServiceInstanceName $sandboxServiceName
				}
				
				if ($GlobalFarmSolutionRestartTimer -ne $null) {
					if ($GlobalFarmSolutionRestartTimer -eq $true) {
						CleanupAndRestartTimer;
					}
				}
			}
		
		}
		elseif ($GlobalFarmSolutionDeployMode -eq "ReDeploy"){
		
			if ((FarmSolutionIsInstalled  $GlobalFarmSolutionWSPName) -eq $true){
			
				if ($GlobalFarmSolutionRestartUserCode -eq $true) {
					StopSharePointServicesInFarm $farm $sandboxServiceInstanceName $sandboxServiceName;
				}
				
				WriteMessage $false $true "Uninstalling Global Farm Solution $GlobalFarmSolutionName."
				UnInstallFarmSolution $GlobalFarmSolutionWSPName;
				
				if ($GlobalFarmSolutionRestartUserCode -eq $true) {
					StartSharePointServicesInFarm $farm $sandboxServiceInstanceName $sandboxServiceName;
				}
				
				if ($GlobalFarmSolutionRestartTimer -ne $null) {
					if ($GlobalFarmSolutionRestartTimer -eq $true) {
						CleanupAndRestartTimer;
					}
				}
				
			}
			
			if ((FarmSolutionIsInstalled $GlobalFarmSolutionWSPName) -eq $false){
		
				WriteMessage $false $true "Installing Global Farm Solution $GlobalFarmSolutionName."
				InstallGlobalFarmSolution $GlobalFarmSolutionWSPName;
				
			}
		}
		elseif ($GlobalFarmSolutionDeployMode -eq "Remove"){
		
			if ((FarmSolutionIsInstalled  $GlobalFarmSolutionWSPName) -eq $true){
			
				if ($GlobalFarmSolutionRestartUserCode -eq $true) {
					StopSharePointServicesInFarm $farm $sandboxServiceInstanceName $sandboxServiceName;
				}
				
				WriteMessage $false $true "Uninstalling Global Farm Solution $GlobalFarmSolutionName."
				UnInstallFarmSolution $GlobalFarmSolutionWSPName;
				
				if ($GlobalFarmSolutionRestartUserCode -eq $true) {
					StartSharePointServicesInFarm $farm $sandboxServiceInstanceName $sandboxServiceName;
				}
				
				if ($GlobalFarmSolutionRestartTimer -ne $null) {
					if ($GlobalFarmSolutionRestartTimer -eq $true) {
						CleanupAndRestartTimer;
					}
				}
			}
		}
			
	}
}

#******************************************************************************************************************************
# Processing Farm Resources
#******************************************************************************************************************************

if ($ChainedFarmFeatures -ne $null){

	foreach($ChainedFarmFeature in $ChainedFarmFeatures) {
	
		$ChainedFarmFeatureName =  $ChainedFarmFeature.Name
		$ChainedFarmFeatureID =  $ChainedFarmFeature.ID
		$ChainedFarmFeatureExternalProcess =  [System.Convert]::ToBoolean($ChainedFarmFeature.ExternalProcess)
		$ChainedFarmFeatureDeployMode =  $ChainedFarmFeature.DeployMode
		
		if ($ChainedFarmFeatureDeployMode -eq "Activate") {

			if ((FarmFeatureIsActivated $ChainedFarmFeatureID) -eq $false){
				WriteMessage $false $true "Activating Farm Chained Feature $ChainedFarmFeatureName."
				if ($ChainedFarmFeatureExternalProcess -eq $false){
					ActivateFarmFeature $ChainedFarmFeatureID;
				}
				else
				{
					ActivateFarmFeatureInAnotherProcess $ChainedFarmFeatureID;
				}
			}

		}
		elseif ($ChainedFarmFeatureDeployMode -eq "Deactivate") {

			if ((FarmFeatureIsActivated $ChainedFarmFeatureID) -eq $true){
				WriteMessage $false $true "Deactivating Farm Chained Feature $ChainedFarmFeatureName."
				if ($ChainedFarmFeatureExternalProcess -eq $false){
					DeactivateFarmFeature $ChainedFarmFeatureID;
				}
				else
				{
					DeactivateFarmFeatureInAnotherProcess $ChainedFarmFeatureID;
				}
			}

		}
		elseif ($ChainedFarmFeatureDeployMode -eq "Reactivate") {

			if ((FarmFeatureIsActivated $ChainedFarmFeatureID) -eq $true){
				WriteMessage $false $true "Deactivating Farm Chained Feature $ChainedFarmFeatureName."
				if ($ChainedFarmFeatureExternalProcess -eq $false){
					DeactivateFarmFeature $ChainedFarmFeatureID;
				}
				else
				{
					DeactivateFarmFeatureInAnotherProcess $ChainedFarmFeatureID;
				}
			}

			if ((FarmFeatureIsActivated $ChainedFarmFeatureID) -eq $false){
				WriteMessage $false $true "Activating Farm Chained Feature $ChainedFarmFeatureName."
				if ($ChainedFarmFeatureExternalProcess -eq $false){
					ActivateFarmFeature $ChainedFarmFeatureID;
				}
				else
				{
					ActivateFarmFeatureInAnotherProcess $ChainedFarmFeatureID;
				}
			}

		}	
			
	}
}

#****************************************************************************************************************************************
# Processing Web Applications
#******************************************************************************************************************************

if ($WebApplications -ne $null){

	foreach($WebApplication in $WebApplications) {

		$WebApplicationName =  $WebApplication.Name;
		$HostWebApplication = GetHostWebApplication $WebApplicationName;
		
		if ($HostWebApplication -ne $null) {
		
			if ([System.String]::IsNullOrEmpty($WebApplication.DropExisting) -eq $false) {
				$WebApplicationDropExisting =  [System.Convert]::ToBoolean($WebApplication.DropExisting);
			} else { $WebApplicationDropExisting = $null;}
			
			if ([System.String]::IsNullOrEmpty($WebApplication.Create) -eq $false) {
				$WebApplicationCreate =  [System.Convert]::ToBoolean($WebApplication.Create);
			} else { $WebApplicationCreate = $null;}
			
			if ([System.String]::IsNullOrEmpty($WebApplication.DisableCoauthoring) -eq $false) {
				$WebApplicationDisableCoauthoring =  [System.Convert]::ToBoolean($WebApplication.DisableCoauthoring);
			} else { $WebApplicationDisableCoauthoring = $null;}
			
			if ([System.String]::IsNullOrEmpty($WebApplication.BrowserFileHandling) -eq $false) {
				$WebApplicationBrowserFileHandling =  $WebApplication.BrowserFileHandling;
			} else { $WebApplicationBrowserFileHandling = $null;}
			
			if ([System.String]::IsNullOrEmpty($WebApplication.MaxQueryLookupFields) -eq $false) {
				$WebApplicationMaxQueryLookupFields = [System.Convert]::ToInt32($WebApplication.MaxQueryLookupFields);
			} else { $WebApplicationMaxQueryLookupFields = $null;}
		
			$WebApplicationURL = $HostWebApplication.URL;
					
			if ($WebApplicationDropExisting -ne $null) {
				if (($WebApplicationDropExisting -eq $true) -and ((WebApplicationExists $WebApplicationURL) -eq $true)){
					WriteMessage $false $true "Dropping Web Application $WebApplicationURL."  -BackgroundColor Black;
					DropWebApplication $WebApplicationURL;
				}
			}

			if ($WebApplicationCreate -ne $null) {
				if (($WebApplicationCreate -eq $true) -and ((WebApplicationExists $WebApplicationURL) -eq $false)){
					WriteMessage $false $true "Creating Web Application $WebApplicationURL.";
					CreateWebApplication $WebApplicationURL;
				}
			}
			
			if ($WebApplicationDisableCoauthoring -ne $null) {
				if (($WebApplicationDisableCoauthoring -eq $true) -and ((WebApplicationHasCoauthoring $WebApplicationURL) -eq $true)){
					WriteMessage $false $true "Disabling Coauthoring for Web Application $WebApplicationURL."  -BackgroundColor Black;
					DisableCoauthoring $WebApplicationURL;
				}
			}
			
			if ($WebApplicationBrowserFileHandling -ne $null) {
				if ((GetBrowserFileHandling $WebApplicationURL) -ne $WebApplicationBrowserFileHandling){
					WriteMessage $false $true "Configuring Browser File Handling for Web Application $WebApplicationURL."  -BackgroundColor Black;
					ConfigBrowserFileHandling $WebApplicationURL $WebApplicationBrowserFileHandling;
				}
			}
			
			if ($WebApplicationMaxQueryLookupFields -ne $null) {
				if ((GetMaxQueryLookupFields $WebApplicationURL) -ne $WebApplicationMaxQueryLookupFields) {
					WriteMessage $false $true "Configuring MaxQueryLookupFields for Web Application $WebApplicationURL."  -BackgroundColor Black;
					ConfigMaxQueryLookupFields $WebApplicationURL $WebApplicationMaxQueryLookupFields;
				}
			}
			
	#******************************************************************************************************************************
	# Processing Web Application Managed Paths
	#******************************************************************************************************************************
			
			if ($WebApplications.ManagedPaths.ManagedPath -ne $null){

				foreach($ManagedPath in $WebApplications.ManagedPaths.ManagedPath) {
				
					$ManagedPathUrl =  $ManagedPath.ManagedPathUrl;
					$ManagedPathUrlDeployMode =  $ManagedPath.DeployMode;
					
					if ([System.String]::IsNullOrEmpty($ManagedPath.Explicit) -eq $false) {
						$ManagedPathExplicit =  [System.Convert]::ToBoolean($ManagedPath.Explicit);
					} else { $ManagedPathExplicit = $false;}
					
					if ($ManagedPathUrlDeployMode -eq "Create"){
						if ((ManagedPathExists  $WebApplicationURL $ManagedPathUrl) -eq $false){
							WriteMessage $false $true "Creating Managed Path $ManagedPathUrl inside Web Application $WebApplicationURL.";
							CreateManagedPath $WebApplicationURL $ManagedPathUrl $ManagedPathExplicit;
						}
					}
					else {
						if ((ManagedPathExists  $WebApplicationURL $ManagedPathUrl) -eq $true){
							WriteMessage $false $true "Dropping Managed Path $ManagedPathUrl inside Web Application $WebApplicationURL.";
							foreach($SPSite in  EnumarateSiteCollectionsInManagedPath $WebApplicationURL $ManagedPathUrl)
							{
								[string]$Temp = $SPSite.Url.ToString();
							
								WriteMessage $false $true "Dropping Site Collection $Temp in $ManagedPathUrl.";
								
								DropSiteCollection $Temp;
								$SPSite.Close();
								$SPSite.Dispose();
							}
							DropManagedPath $WebApplicationURL $ManagedPathUrl;
						}
					}
				}
			}
			
	#******************************************************************************************************************************
	# Processing Web Application Farm Solutions
	#******************************************************************************************************************************
			
			if ($WebApplications.WebApplicationFarmSolutions.WebApplicationFarmSolution -ne $null){

				foreach($WebApplicationFarmSolution in $WebApplications.WebApplicationFarmSolutions.WebApplicationFarmSolution) {
				
					$WebApplicationFarmSolutionName =  $WebApplicationFarmSolution.Name
					$WebApplicationFarmSolutionWSPName =  $WebApplicationFarmSolution.WSPName
					$WebApplicationFarmSolutionDeployMode = $WebApplicationFarmSolution.DeployMode
					$GACDeployment =  [System.Convert]::ToBoolean($WebApplicationFarmSolution.GACDeployment)
					
					if ([System.String]::IsNullOrEmpty($WebApplicationFarmSolution.RestartTimer) -eq $false) {
						$WebApplicationFarmSolutionRestartTimer =  [System.Convert]::ToBoolean($WebApplicationFarmSolution.RestartTimer);
					} else { $WebApplicationFarmSolutionRestartTimer = $null;}
					
					if ($WebApplicationFarmSolutionDeployMode -eq "Deploy"){
						
						if ((FarmSolutionIsInstalled  $WebApplicationFarmSolutionWSPName) -eq $false){
							WriteMessage $false $true "Installing Web Application Farm Solution $WebApplicationFarmSolutionName."
							InstallFarmSolution $WebApplicationFarmSolutionWSPName;
						}
									
						
						if ((FarmSolutionIsInstalled $WebApplicationFarmSolutionWSPName) -eq $true){
							if ((FarmSolutionIsDeployed $WebApplicationFarmSolutionWSPName $WebApplicationURL) -eq $false){
								WriteMessage $false $true "Deploying Web Application Farm Solution $WebApplicationFarmSolutionName to $WebApplicationName."
								DeployWebApplicationFarmSolution $WebApplicationFarmSolutionWSPName $WebApplicationURL $GACDeployment;
								
								if ($WebApplicationFarmSolutionRestartTimer -ne $null) {
									if ($WebApplicationFarmSolutionRestartTimer -eq $true) {
										CleanupAndRestartTimer;
									}
								}
							}
						}	
						
					}
					elseif ($WebApplicationFarmSolutionDeployMode -eq "ReDeploy"){
					
						if ((FarmSolutionIsInstalled  $WebApplicationFarmSolutionWSPName) -eq $true){
							WriteMessage $false $true "Uninstalling Web Application Farm Solution $WebApplicationFarmSolutionName."
							UnInstallFarmSolution $WebApplicationFarmSolutionWSPName;
						}
						
						if ((FarmSolutionIsInstalled  $WebApplicationFarmSolutionWSPName) -eq $false){
							WriteMessage $false $true "Installing Web Application Farm Solution $WebApplicationFarmSolutionName."
							InstallFarmSolution $WebApplicationFarmSolutionWSPName;
						}
									
						
						if ((FarmSolutionIsInstalled $WebApplicationFarmSolutionWSPName) -eq $true){
							if ((FarmSolutionIsDeployed $WebApplicationFarmSolutionWSPName $WebApplicationURL) -eq $false){
								WriteMessage $false $true "Deploying Web Application Farm Solution $WebApplicationFarmSolutionName to $WebApplicationName."
								DeployWebApplicationFarmSolution $WebApplicationFarmSolutionWSPName $WebApplicationURL $GACDeployment;
								
								if ($WebApplicationFarmSolutionRestartTimer -ne $null) {
									if ($WebApplicationFarmSolutionRestartTimer -eq $true) {
										CleanupAndRestartTimer;
									}
								}
							}
						}	
					}
					elseif ($WebApplicationFarmSolutionDeployMode -eq "Remove"){
					
						if ((FarmSolutionIsInstalled  $WebApplicationFarmSolutionWSPName) -eq $true){
							WriteMessage $false $true "Uninstalling Web Application Farm Solution $WebApplicationFarmSolutionName."
							UnInstallFarmSolution $WebApplicationFarmSolutionWSPName;
							
							if ($WebApplicationFarmSolutionRestartTimer -ne $null) {
								if ($WebApplicationFarmSolutionRestartTimer -eq $true) {
									CleanupAndRestartTimer;
								}
							}
						}
					}

				}
			}
			
	#******************************************************************************************************************************
	# Processing web.config Settings
	#******************************************************************************************************************************

			foreach($WebConfigModification in $WebApplication.WebConfigModifications.WebConfigModification) {
					$WebConfigModificationType = $WebConfigModification.Type;
					$WebConfigModificationPath = $WebConfigModification.Path;
					$WebConfigModificationName = $WebConfigModification.Name;
					$WebConfigModificationValue = $WebConfigModification.Value;
					$WebConfigModificationOwner = $WebConfigModification.Owner;
					$WebConfigModificationAction = $WebConfigModification.Action;
					

				switch ($WebConfigModificationAction) { 
			
					"Install" {

						switch ($WebConfigModificationType) { 
					
							"SetAttributeValue" {
							
								if ((WebConfigModificationExists $WebApplicationURL $WebConfigModificationOwner $WebConfigModificationName) -eq $false) {
									WriteMessage $false $true "Installing $WebConfigModificationOwner($WebConfigModificationName) inside $WebApplicationURL $WebConfigModificationOwner"
									InstallWebConfigModification $WebApplicationURL 1 $WebConfigModificationOwner $WebConfigModificationPath $WebConfigModificationName $WebConfigModificationValue;
								}
							}
						}

					}
					"Uninstall" {
					
						if ((WebConfigModificationExists $WebApplicationURL $WebConfigModificationOwner $WebConfigModificationName) -eq $true) {
							WriteMessage $false $true "Uninstalling $WebConfigModificationOwner ($WebConfigModificationName) inside $WebApplicationURL"
							UninstallWebConfigModification $WebApplicationURL $WebConfigModificationOwner $WebConfigModificationName;
						}
					}
				}

			}
			
	#******************************************************************************************************************************
	# Processing Web Application Site Collections
	#******************************************************************************************************************************

			foreach($SiteCollection in $WebApplication.SiteCollections.SiteCollection) {

				if (([System.String]::IsNullOrEmpty($SiteCollection.Name) -eq $false) -and ($SiteCollection.Name -ne "SiteCollection")) {
					$SiteCollectionName =  $SiteCollection.Name;
				} else { $SiteCollectionName = $null;}
								
				$HostSiteCollection = GetHostSiteCollection $HostWebApplication $SiteCollectionName;
				
				if ($HostSiteCollection -ne $null) {
				
					if ([System.String]::IsNullOrEmpty($SiteCollection.Language) -eq $false) {
						$SiteCollectionLanguage =  [System.Convert]::ToInt32($SiteCollection.Language);
					} else { $SiteCollectionLanguage = $null;}
					
					if ([System.String]::IsNullOrEmpty($SiteCollection.Template) -eq $false) {
						$SiteCollectionTemplate =  $SiteCollection.Template;
					} else { $SiteCollectionTemplate = $null;}
					
					if ([System.String]::IsNullOrEmpty($SiteCollection.Description) -eq $false) {
						$SiteCollectionDescription =  $SiteCollection.Description;
					} else { $SiteCollectionDescription = $null;}
								
					if ([System.String]::IsNullOrEmpty($SiteCollection.ConfigureDefaultGroups) -eq $false) {
						$SiteCollectionConfigureDefaultGroups =  [System.Convert]::ToBoolean($SiteCollection.ConfigureDefaultGroups);
					} else { $SiteCollectionConfigureDefaultGroups = $null;}
					
					if ([System.String]::IsNullOrEmpty($SiteCollection.ParserEnabled) -eq $false) {
						$SiteCollectionParserEnabled =  [System.Convert]::ToBoolean($SiteCollection.ParserEnabled);
					} else { $SiteCollectionParserEnabled = $null;}
					
					if ([System.String]::IsNullOrEmpty($SiteCollection.DropExisting) -eq $false) {
						$SiteCollectionDropExisting =  [System.Convert]::ToBoolean($SiteCollection.DropExisting);
					} else { $SiteCollectionDropExisting = $null;}
					
					if ([System.String]::IsNullOrEmpty($SiteCollection.Create) -eq $false) {
						$SiteCollectionCreate =  [System.Convert]::ToBoolean($SiteCollection.Create);
					} else { $SiteCollectionCreate = $null;}
					
					$SiteCollectionManagedPathUrl =  $HostSiteCollection.ManagedPathUrl;
					$SiteCollectionURL =  $WebApplicationURL + $SiteCollectionManagedPathUrl + $HostSiteCollection.URL;
					
					if ($SiteCollectionCreate -ne $null) {
						if ($SiteCollectionCreate -eq $true){
							if ((ManagedPathExists  $WebApplicationURL $SiteCollectionManagedPathUrl) -eq $false){
								WriteMessage $false $true "Creating Managed Path $SiteCollectionManagedPathUrl inside Web Application $WebApplicationURL.";
								
								if ([System.String]::IsNullOrEmpty($HostSiteCollection.URL) -eq $false) {
									CreateManagedPath $WebApplicationURL $SiteCollectionManagedPathUrl $false;
								}
								else {
									CreateManagedPath $WebApplicationURL $SiteCollectionManagedPathUrl $true;
								}
							}
						}
					}

					if ($SiteCollectionDropExisting -ne $null) {
						if (($SiteCollectionDropExisting -eq $true) -and ((SiteCollectionExists $SiteCollectionURL) -eq $true)){
							WriteMessage $false $true "Dropping Site Collection $SiteCollectionName in $SiteCollectionURL.";
							DropSiteCollection $SiteCollectionURL;
						}
					}
					
					if ($SiteCollectionCreate -ne $null) {
						if (($SiteCollectionCreate -eq $true) -and ((SiteCollectionExists $SiteCollectionURL) -eq $false)){
							WriteMessage $false $true "Creating Site Collection $SiteCollectionName in $SiteCollectionURL.";
							CreateSiteCollection $SiteCollectionURL $SiteCollectionName $SiteCollectionLanguage $SiteCollectionTemplate $SiteCollectionDescription;
						}
					}
					
					if ($SiteCollectionConfigureDefaultGroups -ne $null) {
						if (($SiteCollectionConfigureDefaultGroups -eq $true) -and ((NeedConfigureDefaultGroups $SiteCollectionURL) -eq $true)){
							WriteMessage $false $true "Redefining Web Site Default Groups for $SiteCollectionURL.";
							ConfigureDefaultGroups $SiteCollectionURL;
						}
					}
					
					if ($SiteCollectionParserEnabled -ne $null) {
						if ((IsParserEnabled $SiteCollectionURL) -ne $SiteCollectionParserEnabled){
							WriteMessage $false $true "Configuring Parser for $SiteCollectionURL.";
							ConfigParseEnabled $SiteCollectionURL $SiteCollectionParserEnabled;
						}
					}
					
					
		#******************************************************************************************************************************
		# Processing Site Collection Permission Levels
		#******************************************************************************************************************************
					if ($SiteCollection.PermissionLevels.PermissionLevel -ne $null){
						foreach($PermissionLevel in $SiteCollection.PermissionLevels.PermissionLevel) {
							
							$PermissionLevelName = $PermissionLevel.Name
							$PermissionLevelDescription = $PermissionLevel.Description
							$PermissionLevelPermissions = $PermissionLevel.Permissions
							
							if ((IsPermissionLevelExists $SiteCollectionURL $PermissionLevelName) -eq $false){
								WriteMessage $false $true "Creating Permission Level $PermissionLevelName inside $SiteCollectionURL."
								CreatePermissionLevel $SiteCollectionURL $PermissionLevelName $PermissionLevelDescription $PermissionLevelPermissions;
							}
							
						}
					}
					
		#******************************************************************************************************************************
		# Processing Site Collection Internal Resources
		#******************************************************************************************************************************
					if ($SiteCollection.BuiltInSiteFeatures.BuiltInSiteFeature -ne $null){
						foreach($BuiltInSiteFeature in $SiteCollection.BuiltInSiteFeatures.BuiltInSiteFeature) {
							
							$BuiltInSiteFeatureName =  $BuiltInSiteFeature.Name;
							$BuiltInSiteFeatureId =  $BuiltInSiteFeature.Id;
							$BuiltInSiteFeatureDeployMode = $BuiltInSiteFeature.DeployMode;
							
							if ($BuiltInSiteFeatureDeployMode -eq "Activate") {

								if ((SiteFeatureIsActivated $SiteCollectionURL $BuiltInSiteFeatureId) -eq $false){
									WriteMessage $false $true "Activating BultIn Site Feature $BuiltInSiteFeatureName inside $SiteCollectionURL."
									ActivateSiteFeature $SiteCollectionURL $BuiltInSiteFeatureId;
								}

							}
							elseif ($BuiltInSiteFeatureDeployMode -eq "Deactivate") {

								if ((SiteFeatureIsActivated $SiteCollectionURL $BuiltInSiteFeatureId) -eq $true){
									WriteMessage $false $true "Deactivating BultIn Site Feature $BuiltInSiteFeatureName inside $SiteCollectionURL."
									DeactivateSiteFeature $SiteCollectionURL $BuiltInSiteFeatureId;
								}

							}
							elseif ($BuiltInSiteFeatureDeployMode -eq "Reactivate") {

								if ((SiteFeatureIsActivated $SiteCollectionURL $BuiltInSiteFeatureId) -eq $true){
									WriteMessage $false $true "Deactivating BultIn Site Feature $BuiltInSiteFeatureName inside $SiteCollectionURL."
									DeactivateSiteFeature $SiteCollectionURL $BuiltInSiteFeatureId;
								}

								if ((SiteFeatureIsActivated $SiteCollectionURL $BuiltInSiteFeatureId) -eq $false){
									WriteMessage $false $true "Activating BultIn Site Feature $BuiltInSiteFeatureName inside $SiteCollectionURL."
									ActivateSiteFeature $SiteCollectionURL $BuiltInSiteFeatureId;
								}

							}					
						}
					}
					
		#******************************************************************************************************************************
		# Processing Web Site User Solutions on Site Collection
		#******************************************************************************************************************************

					if ($SiteCollection.SandboxSolutions.SandboxSolution -ne $null){
						foreach($SandboxSolution in $SiteCollection.SandboxSolutions.SandboxSolution) {
							
							$SandboxSolutionName =  $SandboxSolution.Name
							$SandboxSolutionWSPName =  $SandboxSolution.WSPName
							$SandboxSolutionDeployMode = $SandboxSolution.DeployMode
							
							if ($SandboxSolutionDeployMode -eq "Deploy"){
								
								if ((SandboxSolutionIsInstalled $SiteCollectionURL $SandboxSolutionWSPName) -eq $false){
									WriteMessage $false $true "Installing SandBox Solution $SandboxSolutionName inside $SiteCollectionURL."
									InstallSandboxSolution $SiteCollectionURL $SandboxSolutionWSPName;
								}						
							}
							elseif ($SandboxSolutionDeployMode -eq "ReDeploy"){
							
								if ((SandboxSolutionIsExists $SiteCollectionURL $SandboxSolutionWSPName) -eq $true){
									WriteMessage $false $true "Uninstalling SandBox Solution $SandboxSolutionName inside $SiteCollectionURL."
									UnInstallSandboxSolution $SiteCollectionURL $SandboxSolutionWSPName;
								}	
								
								if ((SandboxSolutionIsInstalled $SiteCollectionURL $SandboxSolutionWSPName) -eq $false){
									WriteMessage $false $true "Installing SandBox Solution $SandboxSolutionName inside $SiteCollectionURL."
									InstallSandboxSolution $SiteCollectionURL $SandboxSolutionWSPName;
								}
							}
							elseif ($SandboxSolutionDeployMode -eq "Remove"){
							
								if ((SandboxSolutionIsExists $SiteCollectionURL $SandboxSolutionWSPName) -eq $true){
									WriteMessage $false $true "Uninstalling SandBox Solution $SandboxSolutionName inside $SiteCollectionURL."
									UnInstallSandboxSolution $SiteCollectionURL $SandboxSolutionWSPName;
								}
							}
							
						}
					}
					
		#******************************************************************************************************************************
		# Processing User Solutions Resources on Site Collection
		#******************************************************************************************************************************

					if ($SiteCollection.SandboxSiteFeatures.SandboxSiteFeature -ne $null){
						foreach($SandboxSiteFeature in $SiteCollection.SandboxSiteFeatures.SandboxSiteFeature) {
							
							$SandboxSiteFeatureName =  $SandboxSiteFeature.Name
							$SandboxSiteFeatureId =  $SandboxSiteFeature.Id
							$SandboxSiteFeatureDeployMode =  $SandboxSiteFeature.DeployMode

							if ($SandboxSiteFeatureDeployMode -eq "Activate") {

								if ((SiteFeatureIsActivated $SiteCollectionURL $SandboxSiteFeatureId) -eq $false){
									WriteMessage $false $true "Activating Sandbox Site Feature $SandboxSiteFeatureName inside $SiteCollectionURL."
									ActivateSiteFeature $SiteCollectionURL $SandboxSiteFeatureId;
								}

							}
							elseif ($SandboxSiteFeatureDeployMode -eq "Deactivate") {

								if ((SiteFeatureIsActivated $SiteCollectionURL $SandboxSiteFeatureId) -eq $true){
									WriteMessage $false $true "Deactivating Sandbox Site Feature $SandboxSiteFeatureName inside $SiteCollectionURL."
									DeactivateSiteFeature $SiteCollectionURL $SandboxSiteFeatureId;
								}

							}
							elseif ($SandboxSiteFeatureDeployMode -eq "Reactivate") {

								if ((SiteFeatureIsActivated $SiteCollectionURL $SandboxSiteFeatureId) -eq $true){
									WriteMessage $false $true "Deactivating Sandbox Site Feature $SandboxSiteFeatureName inside $SiteCollectionURL."
									DeactivateSiteFeature $SiteCollectionURL $SandboxSiteFeatureId;
								}

								if ((SiteFeatureIsActivated $SiteCollectionURL $SandboxSiteFeatureId) -eq $false){
									WriteMessage $false $true "Activating Sandbox Site Feature $SandboxSiteFeatureName inside $SiteCollectionURL."
									ActivateSiteFeature $SiteCollectionURL $SandboxSiteFeatureId;
								}

							}	

						}
					}
					
					ProcessSites $SiteCollection $SiteCollectionURL;
					
		#******************************************************************************************************************************
		# Processing Site Collection Web Sites 
		#******************************************************************************************************************************

					if ($SiteCollection.WebSites.WebSite -ne $null){
						foreach($WebSite in $SiteCollection.WebSites.WebSite) {
							
							$WebSiteType =  $WebSite.Type;

							if ($WebSiteType -eq "SingleWeb") {
							
								if (([System.String]::IsNullOrEmpty($WebSite.Name) -eq $false) -and ($WebSite.Name -ne "WebSite")) {
									$WebSiteName =  $SiteCollection.Name;
								} else { $WebSiteName = $null;}
								
								if ([System.String]::IsNullOrEmpty($WebSite.Language) -eq $false) {
									$WebSiteLanguage =  [System.Convert]::ToInt32($WebSite.Language);
								} else { $WebSiteLanguage = $null;}
								
								if ([System.String]::IsNullOrEmpty($WebSite.Template) -eq $false) {
									$WebSiteTemplate =  $WebSite.Template;
								} else { $WebSiteTemplate = $null;}
								
								if ([System.String]::IsNullOrEmpty($WebSite.Description) -eq $false) {
									$WebSiteDescription =  $WebSite.Description;
								} else { $WebSiteDescription = $null;}
								
								if ([System.String]::IsNullOrEmpty($WebSite.ParserEnabled) -eq $false) {
									$WebSiteParserEnabled =  [System.Convert]::ToBoolean($WebSite.ParserEnabled);
								} else { $WebSiteParserEnabled = $null;}
														
								if ([System.String]::IsNullOrEmpty($WebSite.Create) -eq $false) {
									$WebSiteCreate = [System.Convert]::ToBoolean($WebSite.Create);
								} else { $WebSiteCreate = $null;}
								
								if ([System.String]::IsNullOrEmpty($WebSite.DropExisting) -eq $false) {
									$WebSiteDropExisting = [System.Convert]::ToBoolean($WebSite.DropExisting);
								} else { $WebSiteDropExisting = $null;}

								if ([System.String]::IsNullOrEmpty($WebSite.ConfigureDefaultGroups) -eq $false) {
									$WebSiteConfigureDefaultGroups = [System.Convert]::ToBoolean($WebSite.ConfigureDefaultGroups);
								} else { $WebSiteConfigureDefaultGroups = $null;}
							
								if ([System.String]::IsNullOrEmpty($WebSite.URL) -eq $false) {
									$WebSiteTempUrl = $WebSite.URL;
								} else { $WebSiteTempUrl = "";}
								
								$WebSiteURL =  $SiteCollectionURL + $WebSiteTempUrl;

								if ($WebSiteDropExisting -ne $null) {
									if (($WebSiteDropExisting -eq $true) -and ((WebSiteExists $SiteCollectionURL $WebSiteURL) -eq $true)){
										WriteMessage $false $true "Dropping Web Site $WebSiteName.";
										DropWebSite $WebSiteURL;
									}
								}

								if ($WebSiteCreate -ne $null) {
									if (($WebSiteCreate -eq $true) -and ((WebSiteExists $SiteCollectionURL $WebSiteURL) -eq $false)){
										WriteMessage $false $true "Creating Web Site $WebSiteName in $WebSiteURL.";
										CreateWebSite $WebSiteURL $WebSiteName $WebSiteLanguage $WebSiteTemplate $WebSiteDescription;
									}
								}
							
								if ((WebSiteExists $SiteCollectionURL $WebSiteURL) -eq $true) {
							
									if ($WebSiteParserEnabled -ne $null) {
										if ((IsParserEnabled $WebSiteURL) -ne $WebSiteParserEnabled){
											WriteMessage $false $true "Configuring Parser for $WebSiteName.";
											ConfigParseEnabled $WebSiteURL $WebSiteParserEnabled;
										}
									}
									
									if ($WebSiteConfigureDefaultGroups -ne $null) {
										if (($WebSiteConfigureDefaultGroups -eq $true) -and ((NeedConfigureDefaultGroups $WebSiteURL) -eq $true)){
											WriteMessage $false $true "Redefining Web Site Default Groups for $WebSiteName.";
											ConfigureDefaultGroups $WebSiteURL;
										}
									}

									ProcessSites $WebSite $WebSiteURL;
								}

							}
							elseif ($WebSiteType -eq "AllSubWebs") {

								$AllSubWebs = Get-SPWeb -Limit All -site $SiteCollectionURL | Where-Object {$_.Url -ne $SiteCollectionURL};

								foreach ($AllSubWeb in $AllSubWebs)
								{
									ProcessSites $WebSite $AllSubWeb.Url;
								}

							}
							elseif ($WebSiteType -eq "SubWebs") {

								$AllSubWebs = Get-SPWeb -Limit All -site $SiteCollectionURL | Where-Object {$_.ParentWeb.Url -eq $WebSiteURL};

								foreach ($AllSubWeb in $AllSubWebs)
								{
									ProcessSites $WebSite $AllSubWeb.Url;
								}
							}	
						}
					}

		#******************************************************************************************************************************
		# Processing Activation of Chainded Resources
		#******************************************************************************************************************************

					if ($SiteCollection.ChainedFeatures.ChainedFeature -ne $null){
						foreach($ChainedFeature in $SiteCollection.ChainedFeatures.ChainedFeature) {
							
							$ChainedFeatureType =  $ChainedFeature.Type;
							$ChainedFeatureName =  $ChainedFeature.Name;
							$ChainedFeatureId =  $ChainedFeature.Id;
							$ChainedFeatureSiteURL =  $ChainedFeature.SiteURL;
							$ChainedFeatureScope =  $ChainedFeature.Scope;
							$ChainedFeatureDeployMode =  $ChainedFeature.DeployMode;
							
							$ChainedFeatureExternalProcess =  $ChainedFeature.ExternalProcess;
							
							$WebSiteURL =  $SiteCollectionURL + $ChainedFeatureSiteURL;
							
							if ($ChainedFeatureDeployMode -eq "Activate") {

								if ((WebSiteFeatureIsActivated $WebSiteURL $ChainedFeatureId $ChainedFeatureScope) -eq $false){
									WriteMessage $false $true "Activating Chained Sandbox $ChainedFeatureScope Feature $ChainedFeatureName inside $WebSiteURL."
									if ([System.Convert]::ToBoolean($ChainedFeatureExternalProcess) -eq $false){
										ActivateWebSiteFeature $WebSiteURL $ChainedFeatureId;
									}
									else
									{
										ActivateFeatureInAnotherProcess $WebSiteURL $ChainedFeatureId;
									}
								}

							}
							elseif ($ChainedFeatureDeployMode -eq "Deactivate") {

								if ((WebSiteFeatureIsActivated $WebSiteURL $ChainedFeatureId $ChainedFeatureScope) -eq $true){
									WriteMessage $false $true "Deactivating Chained $ChainedFeatureScope Feature $ChainedFeatureName inside $WebSiteURL."
									if ([System.Convert]::ToBoolean($ChainedFeatureExternalProcess) -eq $false){
										DeactivateWebSiteFeature $WebSiteURL $ChainedFeatureId;
									}
									else
									{
										DeactivateFeatureInAnotherProcess $WebSiteURL $ChainedFeatureId;
									}
								}

							}
							elseif ($ChainedFeatureDeployMode -eq "Reactivate") {

								if ((WebSiteFeatureIsActivated $WebSiteURL $ChainedFeatureId $ChainedFeatureScope) -eq $true){
									WriteMessage $false $true "Deactivating Chained $ChainedFeatureScope Feature $ChainedFeatureName inside $WebSiteURL."
									if ([System.Convert]::ToBoolean($ChainedFeatureExternalProcess) -eq $false){
										DeactivateWebSiteFeature $WebSiteURL $ChainedFeatureId;
									}
									else
									{
										DeactivateFeatureInAnotherProcess $WebSiteURL $ChainedFeatureId;
									}
								}

								if ((WebSiteFeatureIsActivated $WebSiteURL $ChainedFeatureId $ChainedFeatureScope) -eq $false){
									WriteMessage $false $true "Activating Chained Sandbox $ChainedFeatureScope Feature $ChainedFeatureName inside $WebSiteURL."
									if ([System.Convert]::ToBoolean($ChainedFeatureExternalProcess) -eq $false){
										ActivateWebSiteFeature $WebSiteURL $ChainedFeatureId;
									}
									else
									{
										ActivateFeatureInAnotherProcess $WebSiteURL $ChainedFeatureId;
									}
								}

							}	
							
						}
				
					}
						
		#******************************************************************************************************************************
		# Processing Site Collection Administrators
		#******************************************************************************************************************************

					if ($SiteCollection.SiteCollectionAdmins.NetworkUserOrGroups.NetworkUserOrGroup -ne $null){
						foreach($NetworkUserOrGroup in $SiteCollection.SiteCollectionAdmins.NetworkUserOrGroups.NetworkUserOrGroup) {
							
							$NetworkUserOrGroupLogin = $NetworkUserOrGroup.Login;
							
							if (NetWorkUserOrGroupExists $NetworkUserOrGroupLogin) {
								if ((IsSiteCollectionAdmin $SiteCollectionURL $NetworkUserOrGroupLogin) -eq $false){
									WriteMessage $false $true "Configuring $NetworkUserOrGroupLogin to site collection admin for $SiteCollectionName.";
									AddSiteCollectionAdmin $SiteCollectionURL $NetworkUserOrGroupLogin;
								}
							}
							else {
								WriteMessage $false $true "Cannot find the Network User or Group $NetworkUserOrGroupLogin."
							}
						}
				
					}
				}
			}
		}
		else {
			WriteMessage $false $true "Skipping deploy for $WebApplicationName because the URL cannot be found.";
		}
	}
}
